Index: .project =================================================================== --- .project (revision 0) +++ .project (revision 0) @@ -0,0 +1,23 @@ + + + libcloud + + + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + + org.eclipse.wst.common.project.facet.core.nature + org.python.pydev.pythonNature + + Index: .pydevproject =================================================================== --- .pydevproject (revision 0) +++ .pydevproject (revision 0) @@ -0,0 +1,7 @@ + + + + +Default +python 2.6 + Index: libcloud/providers.py =================================================================== --- libcloud/providers.py (revision 929707) +++ libcloud/providers.py (working copy) @@ -43,6 +43,8 @@ ('libcloud.drivers.voxel', 'VoxelNodeDriver'), Provider.SOFTLAYER: ('libcloud.drivers.softlayer', 'SoftLayerNodeDriver'), + Provider.IBM: + ('libcloud.drivers.ibm', 'IBMNodeDriver') } def get_driver(provider): Index: libcloud/types.py =================================================================== --- libcloud/types.py (revision 929707) +++ libcloud/types.py (working copy) @@ -47,6 +47,7 @@ EC2_US_WEST = 10 VOXEL = 11 SOFTLAYER = 12 + IBM = 13 class NodeState(object): """ Index: libcloud/drivers/ibm.py =================================================================== --- libcloud/drivers/ibm.py (revision 0) +++ libcloud/drivers/ibm.py (revision 0) @@ -0,0 +1,131 @@ +# Licensed to the Apache 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. +# Copyright 2009 RedRata Ltd +""" +Driver for the IBM Developer Cloud. +""" +from libcloud.types import NodeState, InvalidCredsException, Provider +from libcloud.base import Response, ConnectionUserAndKey, NodeDriver, Node, NodeImage, NodeSize, NodeLocation +import base64 + +from xml.etree import ElementTree as ET + +HOST = 'www-180.ibm.com' +REST_BASE = '/cloud/developer/api/rest/20090403' + +class IBMResponse(Response): + def success(self): + return int(self.status) == 200 + + def parse_body(self): + if not self.body: + return None + return ET.XML(self.body) + + def parse_error(self): + return "Oh noes! We encountered an error!" + +class IBMConnection(ConnectionUserAndKey): + """ + Handles the connection to the IBM Developer Cloud. + """ + host = HOST + responseCls = IBMResponse + + def add_default_headers(self, headers): + headers['Accept'] = 'text/xml' + headers['Authorization'] = ('Basic %s' + % (base64.b64encode('%s:%s' % (self.user_id, self.key)))) + return headers + +class IBMNodeDriver(NodeDriver): + """ + IBM Developer Cloud node driver. + """ + connectionCls = IBMConnection + type = Provider.IBM + name = "IBM Developer Cloud" + + NODE_STATE_MAP = { 0: NodeState.PENDING, + 1: NodeState.PENDING, + 2: NodeState.TERMINATED, + 3: NodeState.TERMINATED, + 4: NodeState.TERMINATED, + 5: NodeState.RUNNING, + 6: NodeState.UNKNOWN, + 7: NodeState.PENDING, + 8: NodeState.REBOOTING, + 9: NodeState.PENDING, + 10: NodeState.PENDING, + 11: NodeState.TERMINATED } + + def create_node(self, **kwargs): + pass + + def destroy_node(self, node): + pass + + def reboot_node(self, node): + pass + + def deploy_node(self, **kwargs): + pass + + def list_nodes(self): + return self._to_nodes(self.connection.request(REST_BASE + '/instances').object) + + def list_images(self, location = None): + return self._to_images(self.connection.request(REST_BASE + '/images').object) + + def list_sizes(self, location = None): + # IBM Developer Cloud instances currently support SMALL, MEDIUM, and + # LARGE. Storage also supports SMALL, MEDIUM, and LARGE. + # Can retrieve these dynamically from GET /locations. + return [ NodeSize(0, 'SMALL', None, None, None, None, self.connection.driver), + NodeSize(1, 'MEDIUM', None, None, None, None, self.connection.driver), + NodeSize(2, 'LARGE', None, None, None, None, self.connection.driver) ] + + def list_locations(self): + return self._to_locations(self.connection.request(REST_BASE + '/locations').object) + + def _to_nodes(self, object): + return [ self._to_node(instance) for instance in object.findall('Instance') ] + + + def _to_node(self, instance): + return Node(id = instance.findtext('ID'), + name = instance.findtext('Name'), + state = self.NODE_STATE_MAP[int(instance.findtext('Status'))], + public_ip = instance.findtext('IP'), + private_ip = instance.findtext('IP'), + driver = self.connection.driver) + + def _to_images(self, object): + return [ self._to_image(image) for image in object.findall('Image') ] + + def _to_image(self, image): + return NodeImage(id = image.findtext('ID'), + name = image.findtext('Name'), + driver = self.connection.driver) + + def _to_locations(self, object): + return [ self._to_location(location) for location in object.findall('Location') ] + + def _to_location(self, location): + # NOTE: country currently hardcoded + return NodeLocation(id = location.findtext('ID'), + name = location.findtext('Name'), + country = 'USA', + driver = self.connection.driver)