You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by gm...@apache.org on 2010/02/10 23:31:43 UTC
svn commit: r908690 - in /incubator/libcloud/trunk:
libcloud/drivers/voxel.py libcloud/providers.py libcloud/types.py
test/secrets.py-dist
Author: gmcdonald
Date: Wed Feb 10 22:31:15 2010
New Revision: 908690
URL: http://svn.apache.org/viewvc?rev=908690&view=rev
Log:
Add Voxel support, Due to Upayavira - LIBCLOUD-10
Added:
incubator/libcloud/trunk/libcloud/drivers/voxel.py
Modified:
incubator/libcloud/trunk/libcloud/providers.py
incubator/libcloud/trunk/libcloud/types.py
incubator/libcloud/trunk/test/secrets.py-dist
Added: incubator/libcloud/trunk/libcloud/drivers/voxel.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/drivers/voxel.py?rev=908690&view=auto
==============================================================================
--- incubator/libcloud/trunk/libcloud/drivers/voxel.py (added)
+++ incubator/libcloud/trunk/libcloud/drivers/voxel.py Wed Feb 10 22:31:15 2010
@@ -0,0 +1,248 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# libcloud.org licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+"""
+from libcloud.providers import Provider
+from libcloud.types import NodeState, InvalidCredsException
+from libcloud.base import Node, Response, ConnectionUserAndKey, NodeDriver, NodeSize, NodeImage, NodeLocation
+import urllib2
+import datetime
+import base64
+import hmac
+import httplib
+from hashlib import sha256
+import time
+import urllib
+import hashlib
+from xml.etree import ElementTree as ET
+from xml.parsers.expat import ExpatError
+
+VOXEL_API_HOST = "api.voxel.net"
+
+class VoxelResponse(Response):
+
+ def parse_body(self):
+ if not self.body:
+ return None
+ return ET.XML(self.body)
+
+ def parse_error(self):
+ try:
+ err_list = []
+ for err in ET.XML(self.body).findall('err'):
+ code = err.attrib["code"]
+ message = err.attrib["msg"]
+ err_list.append("%s: %s" % (code.text, message.text))
+ return "\n".join(err_list)
+ except ExpatError:
+ return self.body
+
+class VoxelConnection(ConnectionUserAndKey):
+
+ host = VOXEL_API_HOST
+ responseCls = VoxelResponse
+
+ def add_default_params(self, params):
+ params["key"] = self.user_id
+ params["timestamp"] = datetime.datetime.utcnow().isoformat()+"+0000"
+
+ for param in params.keys():
+ if params[param] is None:
+ del params[param]
+
+ keys = params.keys()
+ keys.sort()
+
+ md5 = hashlib.md5()
+ md5.update(self.key)
+ for key in keys:
+ if params[key]:
+ if not params[key] is None:
+ md5.update("%s%s"% (key, params[key]))
+ else:
+ md5.update(key)
+ params['api_sig'] = md5.hexdigest()
+ return params
+
+VOXEL_INSTANCE_TYPES = {}
+RAM_PER_CPU = 2048
+
+NODE_STATE_MAP = { 'IN_PROGRESS': NodeState.PENDING,
+ 'SUCCEEDED': NodeState.RUNNING,
+ 'shutting-down': NodeState.TERMINATED,
+ 'terminated': NodeState.TERMINATED }
+
+class VoxelNodeDriver(NodeDriver):
+
+ connectionCls = VoxelConnection
+ type = Provider.VOXEL
+ name = 'Voxel VoxCLOUD'
+
+ def initialize_instance_types():
+ 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):
+ return [ NodeSize(driver=self.connection.driver, **i)
+ for i in VOXEL_INSTANCE_TYPES.values() ]
+
+ def list_images(self):
+ params = {"method": "voxel.images.list"}
+ result = self.connection.request('', params=params).object
+ return self._to_images(result)
+
+ name = kwargs["name"]
+ image = kwargs["image"]
+ size = kwargs["size"]
+ params = {'Action': 'RunInstances',
+ 'ImageId': image.id,
+ 'MinCount': kwargs.get('mincount','1'),
+ 'MaxCount': kwargs.get('maxcount','1'),
+ 'InstanceType': size.id}
+
+ try: params['SecurityGroup'] = kwargs['securitygroup']
+ except KeyError: pass
+
+ try: params['KeyName'] = kwargs['keyname']
+ except KeyError: pass
+
+ object = self.connection.request('/', params=params).object
+ nodes = self._to_nodes(object, 'instancesSet/item')
+
+ if len(nodes) == 1:
+ return nodes[0]
+ else: return nodes
+
+ def create_node(self, **kwargs):
+ size = kwargs["size"]
+ cores = size.ram / RAM_PER_CPU
+ params = {'method': 'voxel.voxcloud.create',
+ 'hostname': kwargs["name"],
+ 'disk_size': int(kwargs["disk"])/1024,
+ 'processing_cores': cores,
+ 'facility': kwargs["location"].id,
+ 'image_id': kwargs["image"],
+ 'backend_ip': kwargs.get("privateip", None),
+ 'frontend_ip': kwargs.get("publicip", None),
+ 'admin_password': kwargs.get("rootpass", None),
+ 'console_password': kwargs.get("consolepass", None),
+ 'ssh_username': kwargs.get("sshuser", None),
+ 'ssh_password': kwargs.get("sshpass", None),
+ 'voxel_access': kwargs.get("voxel_access", None)}
+
+ object = self.connection.request('', params=params).object
+
+ if self._getstatus(object):
+ return Node(id = object.findtext("device/id"),
+ name = kwargs["name"],
+ state = NODE_STATE_MAP[object.findtext("devices/status")],
+ public_ip = public_ip,
+ private_ip = private_ip,
+ driver = self.connection.driver)
+ else:
+ return None
+
+ def reboot_node(self, node):
+ """
+ Reboot the node by passing in the node object
+ """
+ params = {'method': 'voxel.devices.power',
+ 'device_id': node.id,
+ 'power_action': 'reboot'}
+ return _getstatus(self.connection.request('', params=params).object)
+
+ def destroy_node(self, node):
+ """
+ Destroy node by passing in the node object
+ """
+ params = {'method': 'voxel.voxcloud.delete',
+ 'device_id': node.id}
+ return _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_ip= public_ip,
+ private_ip= 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
+
Modified: incubator/libcloud/trunk/libcloud/providers.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/providers.py?rev=908690&r1=908689&r2=908690&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/providers.py (original)
+++ incubator/libcloud/trunk/libcloud/providers.py Wed Feb 10 22:31:15 2010
@@ -38,7 +38,9 @@
Provider.LINODE:
('libcloud.drivers.linode', 'LinodeNodeDriver'),
Provider.RIMUHOSTING:
- ('libcloud.drivers.rimuhosting', 'RimuHostingNodeDriver')
+ ('libcloud.drivers.rimuhosting', 'RimuHostingNodeDriver'),
+ Provider.VOXEL:
+ ('libcloud.drivers.voxel', 'VoxelNodeDriver'),
}
def get_driver(provider):
Modified: incubator/libcloud/trunk/libcloud/types.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/types.py?rev=908690&r1=908689&r2=908690&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/types.py (original)
+++ incubator/libcloud/trunk/libcloud/types.py Wed Feb 10 22:31:15 2010
@@ -45,6 +45,7 @@
VCLOUD = 8
RIMUHOSTING = 9
EC2_US_WEST = 10
+ VOXEL = 11
class NodeState(object):
"""
Modified: incubator/libcloud/trunk/test/secrets.py-dist
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/secrets.py-dist?rev=908690&r1=908689&r2=908690&view=diff
==============================================================================
--- incubator/libcloud/trunk/test/secrets.py-dist (original)
+++ incubator/libcloud/trunk/test/secrets.py-dist Wed Feb 10 22:31:15 2010
@@ -38,3 +38,6 @@
TERREMARK_USER=''
TERREMARK_SECRET=''
+
+VOXEL_KEY=''
+VOXEL_SECRET=''