blob: f0e5194695eb41cf90d9061fd3f50a7ffc31c4c3 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT 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):
# pylint: disable=unsubscriptable-object
return "({}) {}".format(self.args[0], self.args[1])
def __repr__(self):
# pylint: disable=unsubscriptable-object
return '<GandiException code {} "{}">'.format(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().__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().request(method, *args)
class BaseGandiDriver:
"""
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:
"""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 = "{}:{}:{}".format(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().__init__(id, state, driver)
self.inet = inet
self.version = version
self.extra = extra or {}
def __repr__(self):
return ("<IPAddress: id=%s, address=%s, state=%s, driver=%s ...>") % (
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().__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 ("<Interface: id=%s, mac=%s, state=%s, driver=%s ...>") % (
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().__init__(id, state, driver)
self.name = name
self.size = size
self.extra = extra or {}
def __repr__(self):
return ("<Disk: id=%s, name=%s, state=%s, size=%s, driver=%s ...>") % (
self.id,
self.name,
self.state,
self.size,
self.driver.name,
)