blob: 75ce4fed1946a71bd0f1e44aac45a368cb2e04a2 [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
import sys
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 '<GandiException code %u "%s">' % (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:
e = sys.exc_info()[1]
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 (('<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(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 (('<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(Disk, self).__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))