This is an automated email from the ASF dual-hosted git repository.
PsiACE pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/libcloud.git
The following commit(s) were added to refs/heads/trunk by this push:
new b3cca53cf Remove Linode APIv3 support (#2132)
b3cca53cf is described below
commit b3cca53cfad8f115fb5f17b67e713447bb9b9dc4
Author: Zhiwei Liang <[email protected]>
AuthorDate: Thu May 7 13:06:48 2026 -0400
Remove Linode APIv3 support (#2132)
Signed-off-by: Zhiwei Liang <[email protected]>
Co-authored-by: Miguel Caballer Fernandez <[email protected]>
---
libcloud/common/linode.py | 144 +---
libcloud/compute/drivers/linode.py | 721 +--------------------
libcloud/dns/drivers/linode.py | 293 +--------
.../fixtures/linode/_avail_datacenters.json | 36 -
.../fixtures/linode/_avail_distributions.json | 246 -------
.../compute/fixtures/linode/_avail_kernels.json | 146 -----
.../fixtures/linode/_avail_linodeplans.json | 158 -----
libcloud/test/compute/fixtures/linode/_batch.json | 22 -
.../compute/fixtures/linode/_linode_disk_list.json | 28 -
.../compute/fixtures/linode/_linode_ip_list.json | 20 -
.../test/compute/fixtures/linode/_linode_list.json | 33 -
libcloud/test/compute/test_linode.py | 208 ------
libcloud/test/compute/test_linode_v4.py | 3 +
.../test/dns/fixtures/linode/create_domain.json | 7 -
.../linode/create_domain_validation_error.json | 10 -
.../test/dns/fixtures/linode/create_resource.json | 7 -
.../test/dns/fixtures/linode/delete_domain.json | 7 -
.../linode/delete_domain_does_not_exist.json | 10 -
.../test/dns/fixtures/linode/delete_resource.json | 7 -
.../linode/delete_resource_does_not_exist.json | 10 -
libcloud/test/dns/fixtures/linode/domain_list.json | 36 -
libcloud/test/dns/fixtures/linode/get_record.json | 18 -
.../fixtures/linode/get_record_does_not_exist.json | 10 -
libcloud/test/dns/fixtures/linode/get_zone.json | 21 -
.../fixtures/linode/get_zone_does_not_exist.json | 10 -
.../test/dns/fixtures/linode/resource_list.json | 30 -
.../linode/resource_list_does_not_exist.json | 10 -
.../test/dns/fixtures/linode/update_domain.json | 7 -
.../test/dns/fixtures/linode/update_resource.json | 7 -
libcloud/test/dns/test_linode.py | 316 ---------
libcloud/test/dns/test_linode_v4.py | 3 +
31 files changed, 12 insertions(+), 2572 deletions(-)
diff --git a/libcloud/common/linode.py b/libcloud/common/linode.py
index 7f0d0e48f..fb1fe24ec 100644
--- a/libcloud/common/linode.py
+++ b/libcloud/common/linode.py
@@ -20,11 +20,7 @@ from libcloud.common.types import LibcloudError,
InvalidCredsError
__all__ = [
"API_HOST",
- "API_ROOT",
"DEFAULT_API_VERSION",
- "LinodeException",
- "LinodeResponse",
- "LinodeConnection",
"LinodeResponseV4",
"LinodeConnectionV4",
"LinodeExceptionV4",
@@ -34,151 +30,13 @@ __all__ = [
# Endpoint for the Linode API
API_HOST = "api.linode.com"
-API_ROOT = "/"
-
DEFAULT_API_VERSION = "4.0"
-# 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"]
LINODE_DISK_FILESYSTEMS_V4 = ["ext3", "ext4", "swap", "raw", "initrd"]
-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 "<LinodeException code %u '%s'>" % (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().__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().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
-
-
class LinodeExceptionV4(Exception):
def __init__(self, message):
self.message = message
@@ -187,7 +45,7 @@ class LinodeExceptionV4(Exception):
return "%s" % self.message
def __repr__(self):
- return "<LinodeException '%s'>" % self.message
+ return "<LinodeExceptionV4 '%s'>" % self.message
class LinodeResponseV4(JsonResponse):
diff --git a/libcloud/compute/drivers/linode.py
b/libcloud/compute/drivers/linode.py
index 81862cdb5..b8da22ea4 100644
--- a/libcloud/compute/drivers/linode.py
+++ b/libcloud/compute/drivers/linode.py
@@ -16,22 +16,16 @@
"""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 API documentation https://www.linode.com/docs/api/
Linode(R) is a registered trademark of Linode, LLC.
"""
-import os
import re
import binascii
-import itertools
-from copy import copy
from datetime import datetime
from libcloud.utils.py3 import httplib
@@ -43,19 +37,12 @@ from libcloud.compute.base import (
NodeDriver,
NodeLocation,
StorageVolume,
- NodeAuthSSHKey,
- NodeAuthPassword,
)
from libcloud.common.linode import (
- API_ROOT,
- LINODE_PLAN_IDS,
DEFAULT_API_VERSION,
- LINODE_DISK_FILESYSTEMS,
LINODE_DISK_FILESYSTEMS_V4,
LinodeDisk,
- LinodeException,
LinodeIPAddress,
- LinodeConnection,
LinodeExceptionV4,
LinodeConnectionV4,
)
@@ -85,9 +72,7 @@ class LinodeNodeDriver(NodeDriver):
**kwargs,
):
if cls is LinodeNodeDriver:
- if api_version == "3.0":
- cls = LinodeNodeDriverV3
- elif api_version == "4.0":
+ if api_version == "4.0":
cls = LinodeNodeDriverV4
else:
raise NotImplementedError(
@@ -96,708 +81,6 @@ class LinodeNodeDriver(NodeDriver):
return super().__new__(cls)
-class LinodeNodeDriverV3(LinodeNodeDriver):
- """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/
- """
-
- connectionCls = LinodeConnection
- _linode_plan_ids = LINODE_PLAN_IDS
- _linode_disk_filesystems = LINODE_DISK_FILESYSTEMS
- features = {"create_node": ["ssh_key", "password"]}
-
- def __init__(
- self,
- key,
- secret=None,
- secure=True,
- host=None,
- port=None,
- api_version=None,
- region=None,
- **kwargs,
- ):
- """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 <https://www.libcloud.org>"
- 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": "[{}] {} Disk Image".format(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 = "{},{},,,,,,,".format(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"] within :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):
- """
- Convert 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
-
- for twenty_five in itertools.zip_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())
-
-
class LinodeNodeDriverV4(LinodeNodeDriver):
connectionCls = LinodeConnectionV4
_linode_disk_filesystems = LINODE_DISK_FILESYSTEMS_V4
diff --git a/libcloud/dns/drivers/linode.py b/libcloud/dns/drivers/linode.py
index b2f609f25..5639a14a4 100644
--- a/libcloud/dns/drivers/linode.py
+++ b/libcloud/dns/drivers/linode.py
@@ -18,15 +18,11 @@ __all__ = ["LinodeDNSDriver"]
from datetime import datetime
from libcloud.dns.base import Zone, Record, DNSDriver
-from libcloud.dns.types import Provider, RecordType, ZoneDoesNotExistError,
RecordDoesNotExistError
+from libcloud.dns.types import Provider, RecordType
from libcloud.utils.py3 import httplib
-from libcloud.utils.misc import get_new_obj, merge_valid_keys
+from libcloud.utils.misc import merge_valid_keys
from libcloud.common.linode import (
- API_ROOT,
DEFAULT_API_VERSION,
- LinodeResponse,
- LinodeException,
- LinodeConnection,
LinodeResponseV4,
LinodeExceptionV4,
LinodeConnectionV4,
@@ -38,17 +34,6 @@ except ImportError:
import json
-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"]
-
VALID_ZONE_EXTRA_PARAMS_V4 = [
"description",
"expire_sec",
@@ -88,9 +73,7 @@ class LinodeDNSDriver(DNSDriver):
**kwargs,
):
if cls is LinodeDNSDriver:
- if api_version == "3.0":
- cls = LinodeDNSDriverV3
- elif api_version == "4.0":
+ if api_version == "4.0":
cls = LinodeDNSDriverV4
else:
raise NotImplementedError(
@@ -99,276 +82,6 @@ class LinodeDNSDriver(DNSDriver):
return super().__new__(cls)
-class LinodeDNSResponse(LinodeResponse):
- def _make_excp(self, error):
- result = super()._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 LinodeDNSDriverV3(LinodeDNSDriver):
- 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
-
-
class LinodeDNSResponseV4(LinodeResponseV4):
pass
diff --git a/libcloud/test/compute/fixtures/linode/_avail_datacenters.json
b/libcloud/test/compute/fixtures/linode/_avail_datacenters.json
deleted file mode 100644
index eb169623b..000000000
--- a/libcloud/test/compute/fixtures/linode/_avail_datacenters.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "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"
-}
\ No newline at end of file
diff --git a/libcloud/test/compute/fixtures/linode/_avail_distributions.json
b/libcloud/test/compute/fixtures/linode/_avail_distributions.json
deleted file mode 100644
index f1bdee61b..000000000
--- a/libcloud/test/compute/fixtures/linode/_avail_distributions.json
+++ /dev/null
@@ -1,246 +0,0 @@
-{
- "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"
-}
\ No newline at end of file
diff --git a/libcloud/test/compute/fixtures/linode/_avail_kernels.json
b/libcloud/test/compute/fixtures/linode/_avail_kernels.json
deleted file mode 100644
index 9552c46c5..000000000
--- a/libcloud/test/compute/fixtures/linode/_avail_kernels.json
+++ /dev/null
@@ -1,146 +0,0 @@
-{
- "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
- }
- ]
-}
\ No newline at end of file
diff --git a/libcloud/test/compute/fixtures/linode/_avail_linodeplans.json
b/libcloud/test/compute/fixtures/linode/_avail_linodeplans.json
deleted file mode 100644
index ac2488934..000000000
--- a/libcloud/test/compute/fixtures/linode/_avail_linodeplans.json
+++ /dev/null
@@ -1,158 +0,0 @@
-{
- "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"
-}
diff --git a/libcloud/test/compute/fixtures/linode/_batch.json
b/libcloud/test/compute/fixtures/linode/_batch.json
deleted file mode 100644
index 36e28f905..000000000
--- a/libcloud/test/compute/fixtures/linode/_batch.json
+++ /dev/null
@@ -1,22 +0,0 @@
-[
- {
- "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"
- }
-]
diff --git a/libcloud/test/compute/fixtures/linode/_linode_disk_list.json
b/libcloud/test/compute/fixtures/linode/_linode_disk_list.json
deleted file mode 100644
index 8ec05a9f1..000000000
--- a/libcloud/test/compute/fixtures/linode/_linode_disk_list.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-"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
- }
- ]
-}
diff --git a/libcloud/test/compute/fixtures/linode/_linode_ip_list.json
b/libcloud/test/compute/fixtures/linode/_linode_ip_list.json
deleted file mode 100644
index 33a969ca6..000000000
--- a/libcloud/test/compute/fixtures/linode/_linode_ip_list.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "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": []
-}
diff --git a/libcloud/test/compute/fixtures/linode/_linode_list.json
b/libcloud/test/compute/fixtures/linode/_linode_list.json
deleted file mode 100644
index 345f7cadb..000000000
--- a/libcloud/test/compute/fixtures/linode/_linode_list.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "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"
-}
diff --git a/libcloud/test/compute/test_linode.py
b/libcloud/test/compute/test_linode.py
deleted file mode 100644
index bbe635448..000000000
--- a/libcloud/test/compute/test_linode.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 <[email protected]>
-# Based upon code written by Alex Polvi <[email protected]>
-#
-
-import sys
-import unittest
-
-from libcloud.test import MockHttp
-from libcloud.utils.py3 import httplib
-from libcloud.compute.base import Node, StorageVolume, NodeAuthSSHKey,
NodeAuthPassword
-from libcloud.test.compute import TestCaseMixin
-from libcloud.test.file_fixtures import ComputeFileFixtures
-from libcloud.compute.drivers.linode import LinodeNodeDriver
-
-
-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", api_version="3.0")
-
- 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())
diff --git a/libcloud/test/compute/test_linode_v4.py
b/libcloud/test/compute/test_linode_v4.py
index ed5d5d2e5..2bae27938 100644
--- a/libcloud/test/compute/test_linode_v4.py
+++ b/libcloud/test/compute/test_linode_v4.py
@@ -47,6 +47,9 @@ class LinodeTestsV4(unittest.TestCase, TestCaseMixin):
def test_unknown_api_version(self):
self.assertRaises(NotImplementedError, LinodeNodeDriver, "foo",
api_version="2.0")
+ def test_removed_api_version(self):
+ self.assertRaises(NotImplementedError, LinodeNodeDriver, "foo",
api_version="3.0")
+
def test_correct_class_is_used(self):
self.assertIsInstance(self.driver, LinodeNodeDriverV4)
diff --git a/libcloud/test/dns/fixtures/linode/create_domain.json
b/libcloud/test/dns/fixtures/linode/create_domain.json
deleted file mode 100644
index a9eef97a0..000000000
--- a/libcloud/test/dns/fixtures/linode/create_domain.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "ERRORARRAY": [],
- "ACTION": "domain.create",
- "DATA": {
- "DomainID": 5094
- }
-}
\ No newline at end of file
diff --git
a/libcloud/test/dns/fixtures/linode/create_domain_validation_error.json
b/libcloud/test/dns/fixtures/linode/create_domain_validation_error.json
deleted file mode 100644
index 3c7059724..000000000
--- a/libcloud/test/dns/fixtures/linode/create_domain_validation_error.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ERRORARRAY": [
- {
- "ERRORCODE": 8,
- "ERRORMESSAGE": "The domain 'linode.com' already exists in our database.
Please open a ticket if you think this is in error."
- }
- ],
- "DATA": {},
- "ACTION": "domain.create"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/create_resource.json
b/libcloud/test/dns/fixtures/linode/create_resource.json
deleted file mode 100644
index 0fa3738e3..000000000
--- a/libcloud/test/dns/fixtures/linode/create_resource.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "ERRORARRAY": [],
- "DATA": {
- "ResourceID": 3585100
- },
- "ACTION": "domain.resource.create"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/delete_domain.json
b/libcloud/test/dns/fixtures/linode/delete_domain.json
deleted file mode 100644
index ff39a38ed..000000000
--- a/libcloud/test/dns/fixtures/linode/delete_domain.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "ERRORARRAY": [],
- "ACTION": "domain.delete",
- "DATA": {
- "DomainID": 5123
- }
-}
\ No newline at end of file
diff --git
a/libcloud/test/dns/fixtures/linode/delete_domain_does_not_exist.json
b/libcloud/test/dns/fixtures/linode/delete_domain_does_not_exist.json
deleted file mode 100644
index 8965baa6e..000000000
--- a/libcloud/test/dns/fixtures/linode/delete_domain_does_not_exist.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ERRORARRAY": [
- {
- "ERRORCODE": 5,
- "ERRORMESSAGE": "Object not found"
- }
- ],
- "DATA": {},
- "ACTION": "domain.delete"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/delete_resource.json
b/libcloud/test/dns/fixtures/linode/delete_resource.json
deleted file mode 100644
index 7f7af2adb..000000000
--- a/libcloud/test/dns/fixtures/linode/delete_resource.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "ERRORARRAY": [],
- "DATA": {
- "ResourceID": 3585141
- },
- "ACTION": "domain.resource.delete"
-}
\ No newline at end of file
diff --git
a/libcloud/test/dns/fixtures/linode/delete_resource_does_not_exist.json
b/libcloud/test/dns/fixtures/linode/delete_resource_does_not_exist.json
deleted file mode 100644
index b6969aa64..000000000
--- a/libcloud/test/dns/fixtures/linode/delete_resource_does_not_exist.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ERRORARRAY": [
- {
- "ERRORCODE": 5,
- "ERRORMESSAGE": "Object not found"
- }
- ],
- "DATA": {},
- "ACTION": "domain.resource.delete"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/domain_list.json
b/libcloud/test/dns/fixtures/linode/domain_list.json
deleted file mode 100644
index ac88b9b5e..000000000
--- a/libcloud/test/dns/fixtures/linode/domain_list.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "ERRORARRAY": [],
- "ACTION": "domain.list",
- "DATA": [
- {
- "DOMAINID": 5093,
- "DESCRIPTION": "",
- "EXPIRE_SEC": 0,
- "RETRY_SEC": 0,
- "STATUS": 1,
- "LPM_DISPLAYGROUP": "thing",
- "MASTER_IPS": "",
- "REFRESH_SEC": 0,
- "SOA_EMAIL": "[email protected]",
- "TTL_SEC": 0,
- "DOMAIN": "linode.com",
- "AXFR_IPS": "none",
- "TYPE": "master"
- },
- {
- "DOMAINID": 5094,
- "DESCRIPTION": "",
- "EXPIRE_SEC": 0,
- "RETRY_SEC": 0,
- "STATUS": 1,
- "LPM_DISPLAYGROUP": "",
- "MASTER_IPS": "2600:3c03::f03c:91ff:feae:e071;66.228.43.47;",
- "REFRESH_SEC": 0,
- "SOA_EMAIL": "",
- "TTL_SEC": 0,
- "DOMAIN": "0.c.d.7.0.6.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa",
- "AXFR_IPS": "2600:3c03::f03c:91ff:feae:e071;66.228.43.47;",
- "TYPE": "slave"
- }
- ]
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/get_record.json
b/libcloud/test/dns/fixtures/linode/get_record.json
deleted file mode 100644
index 4d5b0eb59..000000000
--- a/libcloud/test/dns/fixtures/linode/get_record.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "ERRORARRAY": [],
- "DATA": [
- {
- "DOMAINID": 5093,
- "PORT": 80,
- "RESOURCEID": 3585100,
- "NAME": "www",
- "WEIGHT": 5,
- "TTL_SEC": 0,
- "TARGET": "127.0.0.1",
- "PRIORITY": 10,
- "PROTOCOL": "",
- "TYPE": "a"
- }
- ],
- "ACTION": "domain.resource.list"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/get_record_does_not_exist.json
b/libcloud/test/dns/fixtures/linode/get_record_does_not_exist.json
deleted file mode 100644
index c2c1fb499..000000000
--- a/libcloud/test/dns/fixtures/linode/get_record_does_not_exist.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ERRORARRAY": [
- {
- "ERRORCODE": 5,
- "ERRORMESSAGE": "Object not found"
- }
- ],
- "DATA": {},
- "ACTION": "domain.resource.list"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/get_zone.json
b/libcloud/test/dns/fixtures/linode/get_zone.json
deleted file mode 100644
index e9387122f..000000000
--- a/libcloud/test/dns/fixtures/linode/get_zone.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "ERRORARRAY": [],
- "DATA": [
- {
- "DOMAINID": 5093,
- "DESCRIPTION": "",
- "EXPIRE_SEC": 0,
- "RETRY_SEC": 0,
- "STATUS": 1,
- "LPM_DISPLAYGROUP": "thing",
- "MASTER_IPS": "",
- "REFRESH_SEC": 0,
- "SOA_EMAIL": "[email protected]",
- "TTL_SEC": 0,
- "DOMAIN": "linode.com",
- "AXFR_IPS": "none",
- "TYPE": "master"
- }
- ],
- "ACTION": "domain.list"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/get_zone_does_not_exist.json
b/libcloud/test/dns/fixtures/linode/get_zone_does_not_exist.json
deleted file mode 100644
index ea18547f5..000000000
--- a/libcloud/test/dns/fixtures/linode/get_zone_does_not_exist.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ERRORARRAY": [
- {
- "ERRORCODE": 5,
- "ERRORMESSAGE": "Object not found"
- }
- ],
- "DATA": {},
- "ACTION": "domain.list"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/resource_list.json
b/libcloud/test/dns/fixtures/linode/resource_list.json
deleted file mode 100644
index 2ed18cd82..000000000
--- a/libcloud/test/dns/fixtures/linode/resource_list.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "ERRORARRAY": [],
- "DATA": [
- {
- "DOMAINID": 5093,
- "PORT": 80,
- "RESOURCEID": 3585100,
- "NAME": "mc",
- "WEIGHT": 5,
- "TTL_SEC": 0,
- "TARGET": "127.0.0.1",
- "PRIORITY": 10,
- "PROTOCOL": "",
- "TYPE": "a"
- },
- {
- "DOMAINID": 5093,
- "PORT": 25565,
- "RESOURCEID": 3585141,
- "NAME": "_minecraft._udp",
- "WEIGHT": 5,
- "TTL_SEC": 0,
- "TARGET": "mc.linode.com",
- "PRIORITY": 10,
- "PROTOCOL": "udp",
- "TYPE": "srv"
- }
- ],
- "ACTION": "domain.resource.list"
-}
\ No newline at end of file
diff --git
a/libcloud/test/dns/fixtures/linode/resource_list_does_not_exist.json
b/libcloud/test/dns/fixtures/linode/resource_list_does_not_exist.json
deleted file mode 100644
index c2c1fb499..000000000
--- a/libcloud/test/dns/fixtures/linode/resource_list_does_not_exist.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ERRORARRAY": [
- {
- "ERRORCODE": 5,
- "ERRORMESSAGE": "Object not found"
- }
- ],
- "DATA": {},
- "ACTION": "domain.resource.list"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/update_domain.json
b/libcloud/test/dns/fixtures/linode/update_domain.json
deleted file mode 100644
index f695f4c10..000000000
--- a/libcloud/test/dns/fixtures/linode/update_domain.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "ERRORARRAY": [],
- "DATA": {
- "DomainID": 5093
- },
- "ACTION": "domain.update"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/fixtures/linode/update_resource.json
b/libcloud/test/dns/fixtures/linode/update_resource.json
deleted file mode 100644
index 7f88aabe6..000000000
--- a/libcloud/test/dns/fixtures/linode/update_resource.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "ERRORARRAY": [],
- "DATA": {
- "ResourceID": 3585100
- },
- "ACTION": "domain.resource.update"
-}
\ No newline at end of file
diff --git a/libcloud/test/dns/test_linode.py b/libcloud/test/dns/test_linode.py
deleted file mode 100644
index 7e6b3439b..000000000
--- a/libcloud/test/dns/test_linode.py
+++ /dev/null
@@ -1,316 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "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.test import MockHttp
-from libcloud.dns.types import RecordType, ZoneDoesNotExistError,
RecordDoesNotExistError
-from libcloud.utils.py3 import httplib
-from libcloud.test.secrets import DNS_PARAMS_LINODE, DNS_KEYWORD_PARAMS_LINODE
-from libcloud.common.linode import LinodeException
-from libcloud.dns.drivers.linode import LinodeDNSDriver, LinodeDNSDriverV3
-from libcloud.test.file_fixtures import DNSFileFixtures
-
-
-class LinodeTests(unittest.TestCase):
- def setUp(self):
- LinodeDNSDriverV3.connectionCls.conn_class = LinodeMockHttp
- LinodeMockHttp.use_param = "api_action"
- LinodeMockHttp.type = None
- self.driver = LinodeDNSDriver(*DNS_PARAMS_LINODE,
**DNS_KEYWORD_PARAMS_LINODE)
-
- def assertHasKeys(self, dictionary, keys):
- for key in keys:
- self.assertTrue(key in dictionary, 'key "%s" not in dictionary' %
(key))
-
- def test_list_record_types(self):
- record_types = self.driver.list_record_types()
- self.assertEqual(len(record_types), 7)
- self.assertTrue(RecordType.A in record_types)
-
- def test_list_zones_success(self):
- zones = self.driver.list_zones()
- self.assertEqual(len(zones), 2)
-
- zone = zones[0]
- self.assertEqual(zone.id, "5093")
- self.assertEqual(zone.type, "master")
- self.assertEqual(zone.domain, "linode.com")
- self.assertIsNone(zone.ttl)
- self.assertHasKeys(zone.extra, ["description", "SOA_Email", "status"])
-
- def test_list_records_success(self):
- zone = self.driver.list_zones()[0]
- records = self.driver.list_records(zone=zone)
- self.assertEqual(len(records), 2)
-
- arecord = records[0]
- self.assertEqual(arecord.id, "3585100")
- self.assertEqual(arecord.name, "mc")
- self.assertEqual(arecord.type, RecordType.A)
- self.assertEqual(arecord.data, "127.0.0.1")
- self.assertHasKeys(arecord.extra, ["protocol", "ttl_sec", "port",
"weight"])
-
- srvrecord = records[1]
- self.assertEqual(srvrecord.id, "3585141")
- self.assertEqual(srvrecord.name, "_minecraft._udp")
- self.assertEqual(srvrecord.type, RecordType.SRV)
- self.assertEqual(srvrecord.data, "mc.linode.com")
- self.assertHasKeys(srvrecord.extra, ["protocol", "ttl_sec", "port",
"priority", "weight"])
-
- def test_list_records_zone_does_not_exist(self):
- zone = self.driver.list_zones()[0]
-
- LinodeMockHttp.type = "ZONE_DOES_NOT_EXIST"
- try:
- self.driver.list_records(zone=zone)
- except ZoneDoesNotExistError as e:
- self.assertEqual(e.zone_id, zone.id)
- else:
- self.fail("Exception was not thrown")
-
- def test_get_zone_success(self):
- LinodeMockHttp.type = "GET_ZONE"
-
- zone = self.driver.get_zone(zone_id="5093")
- self.assertEqual(zone.id, "5093")
- self.assertEqual(zone.type, "master")
- self.assertEqual(zone.domain, "linode.com")
- self.assertIsNone(zone.ttl)
- self.assertHasKeys(zone.extra, ["description", "SOA_Email", "status"])
-
- def test_get_zone_does_not_exist(self):
- LinodeMockHttp.type = "GET_ZONE_DOES_NOT_EXIST"
-
- try:
- self.driver.get_zone(zone_id="4444")
- except ZoneDoesNotExistError as e:
- self.assertEqual(e.zone_id, "4444")
- else:
- self.fail("Exception was not thrown")
-
- def test_get_record_success(self):
- LinodeMockHttp.type = "GET_RECORD"
- record = self.driver.get_record(zone_id="1234", record_id="3585100")
- self.assertEqual(record.id, "3585100")
- self.assertEqual(record.name, "www")
- self.assertEqual(record.type, RecordType.A)
- self.assertEqual(record.data, "127.0.0.1")
- self.assertHasKeys(record.extra, ["protocol", "ttl_sec", "port",
"weight"])
-
- def test_get_record_zone_does_not_exist(self):
- LinodeMockHttp.type = "GET_RECORD_ZONE_DOES_NOT_EXIST"
-
- try:
- self.driver.get_record(zone_id="444", record_id="3585100")
- except ZoneDoesNotExistError:
- pass
- else:
- self.fail("Exception was not thrown")
-
- def test_get_record_record_does_not_exist(self):
- LinodeMockHttp.type = "GET_RECORD_RECORD_DOES_NOT_EXIST"
-
- try:
- self.driver.get_record(zone_id="4441", record_id="3585100")
- except RecordDoesNotExistError:
- pass
- else:
- self.fail("Exception was not thrown")
-
- def test_create_zone_success(self):
- zone = self.driver.create_zone(domain="foo.bar.com", type="master",
ttl=None, extra=None)
- self.assertEqual(zone.id, "5094")
- self.assertEqual(zone.domain, "foo.bar.com")
-
- def test_create_zone_validaton_error(self):
- LinodeMockHttp.type = "VALIDATION_ERROR"
-
- try:
- self.driver.create_zone(domain="foo.bar.com", type="master",
ttl=None, extra=None)
- except LinodeException:
- pass
- else:
- self.fail("Exception was not thrown")
-
- def test_update_zone_success(self):
- zone = self.driver.list_zones()[0]
- updated_zone = self.driver.update_zone(
- zone=zone,
- domain="libcloud.org",
- ttl=10,
- extra={"SOA_Email": "[email protected]"},
- )
-
- self.assertEqual(zone.extra["SOA_Email"], "[email protected]")
-
- self.assertEqual(updated_zone.id, zone.id)
- self.assertEqual(updated_zone.domain, "libcloud.org")
- self.assertEqual(updated_zone.type, zone.type)
- self.assertEqual(updated_zone.ttl, 10)
- self.assertEqual(updated_zone.extra["SOA_Email"], "[email protected]")
- self.assertEqual(updated_zone.extra["status"], zone.extra["status"])
- self.assertEqual(updated_zone.extra["description"],
zone.extra["description"])
-
- def test_create_record_success(self):
- zone = self.driver.list_zones()[0]
- record = self.driver.create_record(
- name="www", zone=zone, type=RecordType.A, data="127.0.0.1"
- )
-
- self.assertEqual(record.id, "3585100")
- self.assertEqual(record.name, "www")
- self.assertEqual(record.zone, zone)
- self.assertEqual(record.type, RecordType.A)
- self.assertEqual(record.data, "127.0.0.1")
-
- def test_update_record_success(self):
- zone = self.driver.list_zones()[0]
- record = self.driver.list_records(zone=zone)[0]
- updated_record = self.driver.update_record(
- record=record, name="www", type=RecordType.AAAA, data="::1"
- )
-
- self.assertEqual(record.data, "127.0.0.1")
-
- self.assertEqual(updated_record.id, record.id)
- self.assertEqual(updated_record.name, "www")
- self.assertEqual(updated_record.zone, record.zone)
- self.assertEqual(updated_record.type, RecordType.AAAA)
- self.assertEqual(updated_record.data, "::1")
-
- def test_delete_zone_success(self):
- zone = self.driver.list_zones()[0]
- status = self.driver.delete_zone(zone=zone)
- self.assertTrue(status)
-
- def test_delete_zone_does_not_exist(self):
- zone = self.driver.list_zones()[0]
-
- LinodeMockHttp.type = "ZONE_DOES_NOT_EXIST"
-
- try:
- self.driver.delete_zone(zone=zone)
- except ZoneDoesNotExistError as e:
- self.assertEqual(e.zone_id, zone.id)
- else:
- self.fail("Exception was not thrown")
-
- def test_delete_record_success(self):
- zone = self.driver.list_zones()[0]
- record = self.driver.list_records(zone=zone)[0]
- status = self.driver.delete_record(record=record)
- self.assertTrue(status)
-
- def test_delete_record_does_not_exist(self):
- zone = self.driver.list_zones()[0]
- record = self.driver.list_records(zone=zone)[0]
-
- LinodeMockHttp.type = "RECORD_DOES_NOT_EXIST"
-
- try:
- self.driver.delete_record(record=record)
- except RecordDoesNotExistError as e:
- self.assertEqual(e.record_id, record.id)
- else:
- self.fail("Exception was not thrown")
-
-
-class LinodeMockHttp(MockHttp):
- fixtures = DNSFileFixtures("linode")
-
- def _domain_list(self, method, url, body, headers):
- body = self.fixtures.load("domain_list.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _domain_resource_list(self, method, url, body, headers):
- body = self.fixtures.load("resource_list.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _ZONE_DOES_NOT_EXIST_domain_resource_list(self, method, url, body,
headers):
- body = self.fixtures.load("resource_list_does_not_exist.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_ZONE_domain_list(self, method, url, body, headers):
- body = self.fixtures.load("get_zone.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_ZONE_DOES_NOT_EXIST_domain_list(self, method, url, body, headers):
- body = self.fixtures.load("get_zone_does_not_exist.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_RECORD_domain_list(self, method, url, body, headers):
- body = self.fixtures.load("get_zone.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_RECORD_domain_resource_list(self, method, url, body, headers):
- body = self.fixtures.load("get_record.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_RECORD_ZONE_DOES_NOT_EXIST_domain_list(self, method, url, body,
headers):
- body = self.fixtures.load("get_zone_does_not_exist.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_RECORD_ZONE_DOES_NOT_EXIST_domain_resource_list(self, method,
url, body, headers):
- body = self.fixtures.load("get_record_does_not_exist.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_RECORD_RECORD_DOES_NOT_EXIST_domain_list(self, method, url, body,
headers):
- body = self.fixtures.load("get_zone.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _GET_RECORD_RECORD_DOES_NOT_EXIST_domain_resource_list(self, method,
url, body, headers):
- body = self.fixtures.load("get_record_does_not_exist.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _domain_create(self, method, url, body, headers):
- body = self.fixtures.load("create_domain.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _VALIDATION_ERROR_domain_create(self, method, url, body, headers):
- body = self.fixtures.load("create_domain_validation_error.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _domain_update(self, method, url, body, headers):
- body = self.fixtures.load("update_domain.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _domain_resource_create(self, method, url, body, headers):
- body = self.fixtures.load("create_resource.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _domain_resource_update(self, method, url, body, headers):
- body = self.fixtures.load("update_resource.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _domain_delete(self, method, url, body, headers):
- body = self.fixtures.load("delete_domain.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _ZONE_DOES_NOT_EXIST_domain_delete(self, method, url, body, headers):
- body = self.fixtures.load("delete_domain_does_not_exist.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _domain_resource_delete(self, method, url, body, headers):
- body = self.fixtures.load("delete_resource.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
- def _RECORD_DOES_NOT_EXIST_domain_resource_delete(self, method, url, body,
headers):
- body = self.fixtures.load("delete_resource_does_not_exist.json")
- return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-
-if __name__ == "__main__":
- sys.exit(unittest.main())
diff --git a/libcloud/test/dns/test_linode_v4.py
b/libcloud/test/dns/test_linode_v4.py
index 3b461f74c..df20b360a 100644
--- a/libcloud/test/dns/test_linode_v4.py
+++ b/libcloud/test/dns/test_linode_v4.py
@@ -35,6 +35,9 @@ class LinodeTests(unittest.TestCase):
def test_unknown_api_version(self):
self.assertRaises(NotImplementedError, LinodeDNSDriver, "foo",
api_version="2.0")
+ def test_removed_api_version(self):
+ self.assertRaises(NotImplementedError, LinodeDNSDriver, "foo",
api_version="3.0")
+
def test_list_zones(self):
zones = self.driver.list_zones()
self.assertEqual(len(zones), 3)