You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2011/06/30 14:26:19 UTC
svn commit: r1141506 - in /libcloud/trunk: ./ libcloud/common/
libcloud/compute/ libcloud/compute/drivers/ libcloud/loadbalancer/
libcloud/loadbalancer/drivers/ test/common/ test/compute/
test/compute/fixtures/cloudstack/ test/loadbalancer/ test/loadba...
Author: tomaz
Date: Thu Jun 30 12:26:18 2011
New Revision: 1141506
URL: http://svn.apache.org/viewvc?rev=1141506&view=rev
Log:
Add Ninefold.com compute and load-balancer driver.
The patch has been contributed by Benno Rice <benno at jeamland dot net> and
it's part of LIBCLOUD-98.
Added:
libcloud/trunk/libcloud/common/cloudstack.py
libcloud/trunk/libcloud/compute/drivers/cloudstack.py
libcloud/trunk/libcloud/compute/drivers/ninefold.py
libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py
libcloud/trunk/libcloud/loadbalancer/drivers/ninefold.py
libcloud/trunk/test/common/
libcloud/trunk/test/common/__init__.py
libcloud/trunk/test/common/test_cloudstack.py
libcloud/trunk/test/compute/fixtures/cloudstack/
libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json
libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json
libcloud/trunk/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail.json
libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json
libcloud/trunk/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/listServiceOfferings_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/listTemplates_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/listVirtualMachines_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/listZones_default.json
libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail.json
libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail2.json
libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json
libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json
libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json
libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json
libcloud/trunk/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json
libcloud/trunk/test/compute/test_cloudstack.py
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listZones_default.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json
libcloud/trunk/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json
libcloud/trunk/test/loadbalancer/test_cloudstack.py
Modified:
libcloud/trunk/libcloud/compute/providers.py
libcloud/trunk/libcloud/compute/types.py
libcloud/trunk/libcloud/loadbalancer/base.py
libcloud/trunk/libcloud/loadbalancer/providers.py
libcloud/trunk/libcloud/loadbalancer/types.py
libcloud/trunk/setup.py
Added: libcloud/trunk/libcloud/common/cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/cloudstack.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/libcloud/common/cloudstack.py (added)
+++ libcloud/trunk/libcloud/common/cloudstack.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,124 @@
+# 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.
+
+import base64
+import hashlib
+import hmac
+import time
+import urllib
+
+try:
+ import json
+except:
+ import simplejson as json
+
+from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.common.types import MalformedResponseError
+
+class CloudStackResponse(Response):
+ def parse_body(self):
+ try:
+ body = json.loads(self.body)
+ except:
+ raise MalformedResponseError(
+ "Failed to parse JSON",
+ body=self.body,
+ driver=self.connection.driver)
+ return body
+
+ parse_error = parse_body
+
+class CloudStackConnection(ConnectionUserAndKey):
+ responseCls = CloudStackResponse
+
+ ASYNC_PENDING = 0
+ ASYNC_SUCCESS = 1
+ ASYNC_FAILURE = 2
+
+ def _make_signature(self, params):
+ signature = [(k.lower(), v) for k, v in params.items()]
+ signature.sort(key=lambda x: x[0])
+ signature = urllib.urlencode(signature)
+ signature = signature.lower().replace('+', '%20')
+ signature = hmac.new(self.key, msg=signature, digestmod=hashlib.sha1)
+ return base64.b64encode(signature.digest())
+
+ def add_default_params(self, params):
+ params['apiKey'] = self.user_id
+ params['response'] = 'json'
+
+ return params
+
+ def pre_connect_hook(self, params, headers):
+ params['signature'] = self._make_signature(params)
+
+ return params, headers
+
+ def _sync_request(self, command, **kwargs):
+ """This method handles synchronous calls which are generally fast
+ information retrieval requests and thus return 'quickly'."""
+
+ kwargs['command'] = command
+ result = self.request(self.driver.path, params=kwargs)
+ command = command.lower() + 'response'
+ if command not in result.object:
+ raise MalformedResponseError(
+ "Unknown response format",
+ body=result.body,
+ driver=self.driver)
+ result = result.object[command]
+ return result
+
+ def _async_request(self, command, **kwargs):
+ """This method handles asynchronous calls which are generally
+ requests for the system to do something and can thus take time.
+
+ In these cases the initial call will either fail fast and return
+ an error, or it can return a job ID. We then poll for the status
+ of the job ID which can either be pending, successful or failed."""
+
+ result = self._sync_request(command, **kwargs)
+ job_id = result['jobid']
+ success = True
+
+ while True:
+ result = self._sync_request('queryAsyncJobResult', jobid=job_id)
+ status = result.get('jobstatus', self.ASYNC_PENDING)
+ if status != self.ASYNC_PENDING:
+ break
+ time.sleep(self.driver.async_poll_frequency)
+
+ if result['jobstatus'] == self.ASYNC_FAILURE:
+ raise Exception(result)
+
+ return result['jobresult']
+
+class CloudStackDriverMixIn(object):
+ host = None
+ path = None
+ async_poll_frequency = 1
+
+ connectionCls = CloudStackConnection
+
+ def __init__(self, key, secret=None, secure=True, host=None, port=None):
+ host = host or self.host
+ super(CloudStackDriverMixIn, self).__init__(key, secret, secure, host,
+ port)
+
+ def _sync_request(self, command, **kwargs):
+ return self.connection._sync_request(command, **kwargs)
+
+ def _async_request(self, command, **kwargs):
+ return self.connection._async_request(command, **kwargs)
Added: libcloud/trunk/libcloud/compute/drivers/cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/cloudstack.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/cloudstack.py (added)
+++ libcloud/trunk/libcloud/compute/drivers/cloudstack.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,267 @@
+# 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.
+
+from libcloud.common.cloudstack import CloudStackConnection, \
+ CloudStackDriverMixIn
+from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation, \
+ NodeSize
+from libcloud.compute.types import DeploymentError, NodeState
+
+class CloudStackNode(Node):
+ "Subclass of Node so we can expose our extension methods."
+
+ def ex_allocate_public_ip(self):
+ "Allocate a public IP and bind it to this node."
+ return self.driver.ex_allocate_public_ip(self)
+
+ def ex_release_public_ip(self, address):
+ "Release a public IP that this node holds."
+ return self.driver.ex_release_public_ip(self, address)
+
+ def ex_add_ip_forwarding_rule(self, address, protocol, start_port,
+ end_port=None):
+ "Add a NAT/firewall forwarding rule for a port or ports."
+ return self.driver.ex_add_ip_forwarding_rule(self, address, protocol,
+ start_port, end_port)
+
+ def ex_delete_ip_forwarding_rule(self, rule):
+ "Delete a NAT/firewall rule."
+ return self.driver.ex_delete_ip_forwarding_rule(self, rule)
+
+class CloudStackAddress(object):
+ "A public IP address."
+
+ def __init__(self, node, id, address):
+ self.node = node
+ self.id = id
+ self.address = address
+
+ def release(self):
+ self.node.ex_release_public_ip(self)
+
+ def __str__(self):
+ return self.address
+
+ def __eq__(self, other):
+ return self.__class__ is other.__class__ and self.id == other.id
+
+class CloudStackForwardingRule(object):
+ "A NAT/firewall forwarding rule."
+
+ def __init__(self, node, id, address, protocol, start_port, end_port=None):
+ self.node = node
+ self.id = id
+ self.address = address
+ self.protocol = protocol
+ self.start_port = start_port
+ self.end_port = end_port
+
+ def delete(self):
+ self.node.ex_delete_ip_forwarding_rule(self)
+
+ def __eq__(self, other):
+ return self.__class__ is other.__class__ and self.id == other.id
+
+class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
+ """Driver for the CloudStack API.
+
+ @cvar host: The host where the API can be reached.
+ @cvar path: The path where the API can be reached.
+ @cvar async_poll_frequency: How often (in seconds) to poll for async
+ job completion.
+ @type async_poll_frequency: C{int}"""
+
+ api_name = 'cloudstack'
+
+ NODE_STATE_MAP = {
+ 'Running': NodeState.RUNNING,
+ 'Starting': NodeState.REBOOTING,
+ 'Stopped': NodeState.TERMINATED,
+ 'Stopping': NodeState.TERMINATED
+ }
+
+ def list_images(self, location=None):
+ args = {
+ 'templatefilter': 'executable'
+ }
+ if location is not None:
+ args['zoneid'] = location.id
+ imgs = self._sync_request('listTemplates', **args)
+ images = []
+ for img in imgs['template']:
+ images.append(NodeImage(img['id'], img['name'], self, {
+ 'hypervisor': img['hypervisor'],
+ 'format': img['format'],
+ 'os': img['ostypename'],
+ }))
+ return images
+
+ def list_locations(self):
+ locs = self._sync_request('listZones')
+ locations = []
+ for loc in locs['zone']:
+ locations.append(NodeLocation(loc['id'], loc['name'], 'AU', self))
+ return locations
+
+ def list_nodes(self):
+ vms = self._sync_request('listVirtualMachines')
+ addrs = self._sync_request('listPublicIpAddresses')
+
+ public_ips = {}
+ for addr in addrs['publicipaddress']:
+ if 'virtualmachineid' not in addr:
+ continue
+ vm_id = addr['virtualmachineid']
+ if vm_id not in public_ips:
+ public_ips[vm_id] = {}
+ public_ips[vm_id][addr['ipaddress']] = addr['id']
+
+ nodes = []
+
+ for vm in vms.get('virtualmachine', []):
+ node = CloudStackNode(
+ id=vm['id'],
+ name=vm.get('displayname', None),
+ state=self.NODE_STATE_MAP[vm['state']],
+ public_ip=public_ips.get(vm['id'], {}).keys(),
+ private_ip=[x['ipaddress'] for x in vm['nic']],
+ driver=self,
+ extra={
+ 'zoneid': vm['zoneid'],
+ }
+ )
+
+ addrs = public_ips.get(vm['id'], {}).items()
+ addrs = [CloudStackAddress(node, v, k) for k, v in addrs]
+ node.extra['ip_addresses'] = addrs
+
+ rules = []
+ for addr in addrs:
+ result = self._sync_request('listIpForwardingRules')
+ for r in result.get('ipforwardingrule', []):
+ rule = CloudStackForwardingRule(node, r['id'], addr,
+ r['protocol'].upper(),
+ r['startport'],
+ r['endport'])
+ rules.append(rule)
+ node.extra['ip_forwarding_rules'] = rules
+
+ nodes.append(node)
+
+ return nodes
+
+ def list_sizes(self, location=None):
+ szs = self._sync_request('listServiceOfferings')
+ sizes = []
+ for sz in szs['serviceoffering']:
+ sizes.append(NodeSize(sz['id'], sz['name'], sz['memory'], 0, 0,
+ 0, self))
+ return sizes
+
+ def create_node(self, name, size, image, location=None, **kwargs):
+ if location is None:
+ location = self.list_locations()[0]
+
+ networks = self._sync_request('listNetworks')
+ network_id = networks['network'][0]['id']
+
+ result = self._async_request('deployVirtualMachine',
+ name=name,
+ displayname=name,
+ serviceofferingid=size.id,
+ templateid=image.id,
+ zoneid=location.id,
+ networkids=network_id,
+ )
+
+ node = result['virtualmachine']
+
+ return Node(
+ id=node['id'],
+ name=node['displayname'],
+ state=self.NODE_STATE_MAP[node['state']],
+ public_ip=[],
+ private_ip=[x['ipaddress'] for x in node['nic']],
+ driver=self,
+ extra={
+ 'zoneid': location.id,
+ 'ip_addresses': [],
+ 'forwarding_rules': [],
+ }
+ )
+
+ def destroy_node(self, node):
+ self._async_request('destroyVirtualMachine', id=node.id)
+ return True
+
+ def reboot_node(self, node):
+ self._async_request('rebootVirtualMachine', id=node.id)
+ return True
+
+ def ex_allocate_public_ip(self, node):
+ "Allocate a public IP and bind it to a node."
+
+ zoneid = node.extra['zoneid']
+ addr = self._async_request('associateIpAddress', zoneid=zoneid)
+ addr = addr['ipaddress']
+ result = self._sync_request('enableStaticNat', virtualmachineid=node.id,
+ ipaddressid=addr['id'])
+ if result.get('success', '').lower() != 'true':
+ return None
+
+ node.public_ip.append(addr['ipaddress'])
+ addr = CloudStackAddress(node, addr['id'], addr['ipaddress'])
+ node.extra['ip_addresses'].append(addr)
+ return addr
+
+ def ex_release_public_ip(self, node, address):
+ "Release a public IP."
+
+ node.extra['ip_addresses'].remove(address)
+ node.public_ip.remove(address.address)
+
+ self._async_request('disableStaticNat', ipaddressid=address.id)
+ self._async_request('disassociateIpAddress', id=address.id)
+ return True
+
+ def ex_add_ip_forwarding_rule(self, node, address, protocol,
+ start_port, end_port=None):
+ "Add a NAT/firewall forwarding rule."
+
+ protocol = protocol.upper()
+ if protocol not in ('TCP', 'UDP'):
+ return None
+
+ args = {
+ 'ipaddressid': address.id,
+ 'protocol': protocol,
+ 'startport': int(start_port)
+ }
+ if end_port is not None:
+ args['endport'] = int(end_port)
+
+ result = self._async_request('createIpForwardingRule', **args)
+ result = result['ipforwardingrule']
+ rule = CloudStackForwardingRule(node, result['id'], address,
+ protocol, start_port, end_port)
+ node.extra['ip_forwarding_rules'].append(rule)
+ return rule
+
+ def ex_delete_ip_forwarding_rule(self, node, rule):
+ "Remove a NAT/firewall forwading rule."
+
+ node.extra['ip_forwarding_rules'].remove(rule)
+ self._async_request('deleteIpForwardingRule', id=rule.id)
+ return True
Added: libcloud/trunk/libcloud/compute/drivers/ninefold.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/ninefold.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/ninefold.py (added)
+++ libcloud/trunk/libcloud/compute/drivers/ninefold.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,27 @@
+# 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.
+
+from libcloud.compute.providers import Provider
+
+from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver
+
+class NinefoldNodeDriver(CloudStackNodeDriver):
+ "Driver for Ninefold's Compute platform."
+
+ host = 'api.ninefold.com'
+ path = '/compute/v1.0/'
+
+ type = Provider.NINEFOLD
+ name = 'Ninefold'
Modified: libcloud/trunk/libcloud/compute/providers.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/providers.py?rev=1141506&r1=1141505&r2=1141506&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/providers.py (original)
+++ libcloud/trunk/libcloud/compute/providers.py Thu Jun 30 12:26:18 2011
@@ -89,6 +89,8 @@ DRIVERS = {
('libcloud.compute.drivers.opsource', 'OpsourceNodeDriver'),
Provider.OPENSTACK:
('libcloud.compute.drivers.rackspace', 'OpenStackNodeDriver'),
+ Provider.NINEFOLD:
+ ('libcloud.compute.drivers.ninefold', 'NinefoldNodeDriver'),
}
def get_driver(provider):
Modified: libcloud/trunk/libcloud/compute/types.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/types.py?rev=1141506&r1=1141505&r2=1141506&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/types.py (original)
+++ libcloud/trunk/libcloud/compute/types.py Thu Jun 30 12:26:18 2011
@@ -54,6 +54,7 @@ class Provider(object):
@cvar NIMBUS: Nimbus
@cvar BLUEBOX: Bluebox
@cvar OPSOURCE: Opsource Cloud
+ @cvar NINEFOLD: Ninefold
"""
DUMMY = 0
EC2 = 1 # deprecated name
@@ -91,6 +92,7 @@ class Provider(object):
OPENSTACK = 31
SKALICLOUD = 32
SERVERLOVE = 33
+ NINEFOLD = 34
class NodeState(object):
"""
Modified: libcloud/trunk/libcloud/loadbalancer/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/base.py?rev=1141506&r1=1141505&r2=1141506&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/base.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/base.py Thu Jun 30 12:26:18 2011
@@ -83,7 +83,7 @@ class Driver(object):
_ALGORITHM_TO_VALUE_MAP = {}
_VALUE_TO_ALGORITHM_MAP = {}
- def __init__(self, key, secret=None, secure=True):
+ def __init__(self, key, secret=None, secure=True, host=None, port=None):
self.key = key
self.secret = secret
args = [self.key]
@@ -93,6 +93,12 @@ class Driver(object):
args.append(secure)
+ if host != None:
+ args.append(host)
+
+ if port != None:
+ args.append(port)
+
self.connection = self.connectionCls(*args)
self.connection.driver = self
self.connection.connect()
Added: libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py (added)
+++ libcloud/trunk/libcloud/loadbalancer/drivers/cloudstack.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,123 @@
+# 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.
+
+from libcloud.common.cloudstack import CloudStackConnection, \
+ CloudStackDriverMixIn
+from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm
+from libcloud.loadbalancer.base import DEFAULT_ALGORITHM
+from libcloud.loadbalancer.types import State, LibcloudLBImmutableError
+from libcloud.utils import reverse_dict
+
+class CloudStackLBDriver(CloudStackDriverMixIn, Driver):
+ """Driver for CloudStack load balancers."""
+
+ api_name = 'cloudstack_lb'
+
+ _VALUE_TO_ALGORITHM_MAP = {
+ 'roundrobin': Algorithm.ROUND_ROBIN,
+ 'leastconn': Algorithm.LEAST_CONNECTIONS
+ }
+ _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP)
+
+ LB_STATE_MAP = {
+ 'Active': State.RUNNING,
+ }
+
+ def list_protocols(self):
+ """We don't actually have any protocol awareness beyond TCP."""
+ return [ 'tcp' ]
+
+ def list_balancers(self):
+ balancers = self._sync_request('listLoadBalancerRules')
+ balancers = balancers.get('loadbalancerrule', [])
+ return [self._to_balancer(balancer) for balancer in balancers]
+
+ def get_balancer(self, balancer_id):
+ balancer = self._sync_request('listLoadBalancerRules', id=balancer_id)
+ balancer = balancer.get('loadbalancerrule', [])
+ if not balancer:
+ raise Exception("no such load balancer: " + str(balancer_id))
+ return self._to_balancer(balancer[0])
+
+ def create_balancer(self, name, members, protocol='http', port=80,
+ algorithm=DEFAULT_ALGORITHM, location=None,
+ private_port=None):
+ if location is None:
+ locations = self._sync_request('listZones')
+ location = locations['zone'][0]['id']
+ else:
+ location = location.id
+ if private_port is None:
+ private_port = port
+
+ result = self._async_request('associateIpAddress', zoneid=location)
+ public_ip = result['ipaddress']
+
+ result = self._sync_request('createLoadBalancerRule',
+ algorithm=self._ALGORITHM_TO_VALUE_MAP[algorithm],
+ name=name,
+ privateport=private_port,
+ publicport=port,
+ publicipid=public_ip['id'],
+ )
+
+ balancer = self._to_balancer(result['loadbalancer'])
+
+ for member in members:
+ balancer.attach_member(member)
+
+ return balancer
+
+ def destroy_balancer(self, balancer):
+ self._async_request('deleteLoadBalancerRule', id=balancer.id)
+ self._async_request('disassociateIpAddress',
+ id=balancer.ex_public_ip_id)
+
+ def balancer_attach_member(self, balancer, member):
+ member.port = balancer.ex_private_port
+ self._async_request('assignToLoadBalancerRule', id=balancer.id,
+ virtualmachineids=member.id)
+ return True
+
+ def balancer_detach_member(self, balancer, member):
+ self._async_request('removeFromLoadBalancerRule', id=balancer.id,
+ virtualmachineids=member.id)
+ return True
+
+ def balancer_list_members(self, balancer):
+ members = self._sync_request('listLoadBalancerRuleInstances',
+ id=balancer.id)
+ members = members['loadbalancerruleinstance']
+ return [self._to_member(m, balancer.ex_private_port) for m in members]
+
+ def _to_balancer(self, obj):
+ balancer = LoadBalancer(
+ id=obj['id'],
+ name=obj['name'],
+ state=self.LB_STATE_MAP.get(obj['state'], State.UNKNOWN),
+ ip=obj['publicip'],
+ port=obj['publicport'],
+ driver=self.connection.driver
+ )
+ balancer.ex_private_port = obj['privateport']
+ balancer.ex_public_ip_id = obj['publicipid']
+ return balancer
+
+ def _to_member(self, obj, port):
+ return Member(
+ id=obj['id'],
+ ip=obj['nic'][0]['ipaddress'],
+ port=port
+ )
Added: libcloud/trunk/libcloud/loadbalancer/drivers/ninefold.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/drivers/ninefold.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/drivers/ninefold.py (added)
+++ libcloud/trunk/libcloud/loadbalancer/drivers/ninefold.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,27 @@
+# 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.
+
+from libcloud.loadbalancer.providers import Provider
+
+from libcloud.loadbalancer.drivers.cloudstack import CloudStackLBDriver
+
+class NinefoldLBDriver(CloudStackLBDriver):
+ "Driver for load balancers on Ninefold's Compute platform."
+
+ host = 'api.ninefold.com'
+ path = '/compute/v1.0/'
+
+ type = Provider.NINEFOLD
+ name = 'Ninefold LB'
Modified: libcloud/trunk/libcloud/loadbalancer/providers.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/providers.py?rev=1141506&r1=1141505&r2=1141506&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/providers.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/providers.py Thu Jun 30 12:26:18 2011
@@ -27,6 +27,8 @@ DRIVERS = {
('libcloud.loadbalancer.drivers.rackspace', 'RackspaceLBDriver'),
Provider.GOGRID:
('libcloud.loadbalancer.drivers.gogrid', 'GoGridLBDriver'),
+ Provider.NINEFOLD:
+ ('libcloud.loadbalancer.drivers.ninefold', 'NinefoldLBDriver'),
}
def get_driver(provider):
Modified: libcloud/trunk/libcloud/loadbalancer/types.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/types.py?rev=1141506&r1=1141505&r2=1141506&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/types.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/types.py Thu Jun 30 12:26:18 2011
@@ -29,6 +29,7 @@ class LibcloudLBImmutableError(LibcloudL
class Provider(object):
RACKSPACE_US = 0
GOGRID = 1
+ NINEFOLD = 2
class State(object):
"""
Modified: libcloud/trunk/setup.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/setup.py?rev=1141506&r1=1141505&r2=1141506&view=diff
==============================================================================
--- libcloud/trunk/setup.py (original)
+++ libcloud/trunk/setup.py Thu Jun 30 12:26:18 2011
@@ -29,7 +29,8 @@ libcloud.utils.SHOW_DEPRECATION_WARNING
HTML_VIEWSOURCE_BASE = 'https://svn.apache.org/viewvc/libcloud/trunk'
PROJECT_BASE_DIR = 'http://libcloud.apache.org'
-TEST_PATHS = [ 'test', 'test/compute', 'test/storage' , 'test/loadbalancer']
+TEST_PATHS = ['test', 'test/common', 'test/compute', 'test/storage',
+ 'test/loadbalancer']
DOC_TEST_MODULES = [ 'libcloud.compute.drivers.dummy',
'libcloud.storage.drivers.dummy' ]
Added: libcloud/trunk/test/common/__init__.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/common/__init__.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/common/__init__.py (added)
+++ libcloud/trunk/test/common/__init__.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,14 @@
+# 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.
Added: libcloud/trunk/test/common/test_cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/common/test_cloudstack.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/common/test_cloudstack.py (added)
+++ libcloud/trunk/test/common/test_cloudstack.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,181 @@
+import httplib
+import sys
+import unittest
+import urlparse
+
+try:
+ import json
+except:
+ import simplejson as json
+
+from libcloud.common.cloudstack import CloudStackConnection, CloudStackResponse
+from libcloud.common.types import MalformedResponseError
+
+from test import MockHttpTestCase
+
+async_delay = 0
+
+class CloudStackMockDriver(object):
+ host = 'nonexistant.'
+ path = '/path'
+ async_poll_frequency = 0
+
+ name = 'fake'
+
+ async_delay = 0
+
+class CloudStackCommonTest(unittest.TestCase):
+ def setUp(self):
+ CloudStackConnection.conn_classes = (None, CloudStackMockHttp)
+ self.connection = CloudStackConnection('apikey', 'secret',
+ host=CloudStackMockDriver.host)
+ self.driver = self.connection.driver = CloudStackMockDriver()
+
+ def test_sync_request_bad_response(self):
+ self.driver.path = '/bad/response'
+ try:
+ self.connection._sync_request('fake')
+ except Exception, e:
+ self.assertTrue(isinstance(e, MalformedResponseError))
+ return
+ self.assertTrue(False)
+
+ def test_sync_request(self):
+ self.driver.path = '/sync'
+ self.connection._sync_request('fake')
+
+ def test_async_request_successful(self):
+ self.driver.path = '/async/success'
+ result = self.connection._async_request('fake')
+ self.assertEqual(result, {'fake': 'result'})
+
+ def test_async_request_unsuccessful(self):
+ self.driver.path = '/async/fail'
+ try:
+ self.connection._async_request('fake')
+ except:
+ return
+ self.assertFalse(True)
+
+ def test_async_request_delayed(self):
+ global async_delay
+ self.driver.path = '/async/delayed'
+ async_delay = 2
+ self.connection._async_request('fake')
+ self.assertEqual(async_delay, 0)
+
+ def test_signature_algorithm(self):
+ cases = [
+ (
+ {
+ 'command': 'listVirtualMachines'
+ }, 'z/a9Y7J52u48VpqIgiwaGUMCso0='
+ ), (
+ {
+ 'command': 'deployVirtualMachine',
+ 'name': 'fred',
+ 'displayname': 'George',
+ 'serviceofferingid': 5,
+ 'templateid': 17,
+ 'zoneid': 23,
+ 'networkids': 42
+ }, 'gHTo7mYmadZ+zluKHzlEKb1i/QU='
+ ), (
+ {
+ 'command': 'deployVirtualMachine',
+ 'name': 'fred',
+ 'displayname': 'George+Ringo',
+ 'serviceofferingid': 5,
+ 'templateid': 17,
+ 'zoneid': 23,
+ 'networkids': 42
+ }, 'tAgfrreI1ZvWlWLClD3gu4+aKv4='
+ )
+ ]
+
+ connection = CloudStackConnection('fnord', 'abracadabra')
+ for case in cases:
+ params = connection.add_default_params(case[0])
+ self.assertEqual(connection._make_signature(params), case[1])
+
+class CloudStackMockHttp(MockHttpTestCase):
+ def _response(self, status, result, response):
+ return (status, json.dumps(result), result, response)
+
+ def _check_request(self, url):
+ url = urlparse.urlparse(url)
+ query = dict(urlparse.parse_qsl(url.query))
+
+ self.assertTrue('apiKey' in query)
+ self.assertTrue('command' in query)
+ self.assertTrue('response' in query)
+ self.assertTrue('signature' in query)
+
+ self.assertTrue(query['response'] == 'json')
+
+ return query
+
+ def _bad_response(self, method, url, body, headers):
+ self._check_request(url)
+ result = {'success': True}
+ return self._response(httplib.OK, result, httplib.responses[httplib.OK])
+
+ def _sync(self, method, url, body, headers):
+ query = self._check_request(url)
+ result = {query['command'].lower() + 'response': {}}
+ return self._response(httplib.OK, result, httplib.responses[httplib.OK])
+
+ def _async_success(self, method, url, body, headers):
+ query = self._check_request(url)
+ if query['command'].lower() == 'queryasyncjobresult':
+ self.assertEqual(query['jobid'], '42')
+ result = {
+ query['command'].lower() + 'response': {
+ 'jobstatus': 1,
+ 'jobresult': {'fake': 'result'}
+ }
+ }
+ else:
+ result = {query['command'].lower() + 'response': {'jobid': '42'}}
+ return self._response(httplib.OK, result, httplib.responses[httplib.OK])
+
+ def _async_fail(self, method, url, body, headers):
+ query = self._check_request(url)
+ if query['command'].lower() == 'queryasyncjobresult':
+ self.assertEqual(query['jobid'], '42')
+ result = {
+ query['command'].lower() + 'response': {
+ 'jobstatus': 2,
+ 'jobresult': {'fake': 'failresult'}
+ }
+ }
+ else:
+ result = {query['command'].lower() + 'response': {'jobid': '42'}}
+ return self._response(httplib.OK, result, httplib.responses[httplib.OK])
+
+ def _async_delayed(self, method, url, body, headers):
+ global async_delay
+
+ query = self._check_request(url)
+ if query['command'].lower() == 'queryasyncjobresult':
+ self.assertEqual(query['jobid'], '42')
+ if async_delay == 0:
+ result = {
+ query['command'].lower() + 'response': {
+ 'jobstatus': 1,
+ 'jobresult': {'fake': 'result'}
+ }
+ }
+ else:
+ result = {
+ query['command'].lower() + 'response': {
+ 'jobstatus': 0,
+ }
+ }
+ async_delay -= 1
+ else:
+ result = {query['command'].lower() + 'response': {'jobid': '42'}}
+ return self._response(httplib.OK, result, httplib.responses[httplib.OK])
+
+if __name__ == '__main__':
+ sys.exit(unittest.main())
Added: libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "deployvirtualmachineresponse" : {"jobid":17164,"id":2602} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "deployvirtualmachineresponse" : {"errorcode" : 431, "errortext" : "Unable to find service offering: 104"} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "deployvirtualmachineresponse" : {"jobid":17177,"id":2602} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "destroyvirtualmachineresponse" : {"jobid":17166} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listnetworksresponse" : { "network" : [ {"id":860,"name":"Virtual Network","displaytext":"A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.","broadcastdomaintype":"Vlan","traffictype":"Guest","zoneid":1,"networkofferingid":6,"networkofferingname":"DefaultVirtualizedNetworkOffering","networkofferingdisplaytext":"Virtual Vlan","networkofferingavailability":"Required","isshared":false,"issystem":false,"state":"Implemented","related":860,"broadcasturi":"vlan://1459","dns1":"1.1.1.1","dns2":"1.1.1.2","type":"Virtual","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","isdefault":true,"service":[{"name":"Gateway"},{"name":"Firewall","capability":[{"name":"MultipleIps","value":"true"},{"name":"TrafficStatistics","value":"per public ip"},{"name":"StaticNat","value":"true"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedSourceNa
tTypes","value":"per account"}]},{"name":"UserData"},{"name":"Dns"},{"name":"Dhcp"},{"name":"Lb","capability":[{"name":"TrafficStatistics","value":"per public ip"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn"}]}],"networkdomain":"cs363local","securitygroupenabled":false} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listnetworksresponse" : { "network" : [ {"id":860,"name":"Virtual Network","displaytext":"A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.","broadcastdomaintype":"Vlan","traffictype":"Guest","zoneid":1,"networkofferingid":6,"networkofferingname":"DefaultVirtualizedNetworkOffering","networkofferingdisplaytext":"Virtual Vlan","networkofferingavailability":"Required","isshared":false,"issystem":false,"state":"Implemented","related":860,"broadcasturi":"vlan://1459","dns1":"1.1.1.1","dns2":"1.1.1.2","type":"Virtual","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","isdefault":true,"service":[{"name":"Gateway"},{"name":"Firewall","capability":[{"name":"MultipleIps","value":"true"},{"name":"TrafficStatistics","value":"per public ip"},{"name":"StaticNat","value":"true"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedSourceNa
tTypes","value":"per account"}]},{"name":"UserData"},{"name":"Dns"},{"name":"Dhcp"},{"name":"Lb","capability":[{"name":"TrafficStatistics","value":"per public ip"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn"}]}],"networkdomain":"cs363local","securitygroupenabled":false} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listnetworksresponse" : { "network" : [ {"id":860,"name":"Virtual Network","displaytext":"A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.","broadcastdomaintype":"Vlan","traffictype":"Guest","zoneid":1,"networkofferingid":6,"networkofferingname":"DefaultVirtualizedNetworkOffering","networkofferingdisplaytext":"Virtual Vlan","networkofferingavailability":"Required","isshared":false,"issystem":false,"state":"Implemented","related":860,"broadcasturi":"vlan://1459","dns1":"1.1.1.1","dns2":"1.1.1.2","type":"Virtual","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","isdefault":true,"service":[{"name":"Gateway"},{"name":"Firewall","capability":[{"name":"MultipleIps","value":"true"},{"name":"TrafficStatistics","value":"per public ip"},{"name":"StaticNat","value":"true"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedSourceNa
tTypes","value":"per account"}]},{"name":"UserData"},{"name":"Dns"},{"name":"Dhcp"},{"name":"Lb","capability":[{"name":"TrafficStatistics","value":"per public ip"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn"}]}],"networkdomain":"cs363local","securitygroupenabled":false} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listpublicipaddressesresponse" : { "publicipaddress" : [ {"id":34000,"ipaddress":"1.1.1.49","allocated":"2011-06-23T05:20:39+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33999,"ipaddress":"1.1.1.48","allocated":"2011-06-23T05:20:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33998,"ipaddress":"1.1.1.47","allocated":"2011-06-23T05:20:30+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":3397
0,"ipaddress":"1.1.1.19","allocated":"2011-06-20T04:08:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":true,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listServiceOfferings_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listServiceOfferings_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listServiceOfferings_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listServiceOfferings_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listserviceofferingsresponse" : { "serviceoffering" : [ {"id":105,"name":"Compute Micro PRD","displaytext":"1CPU, 384MB, 80GB HDD","cpunumber":1,"cpuspeed":1200,"memory":384,"created":"2011-06-01T03:38:05+0000","storagetype":"shared","offerha":false,"domainid":14,"domain":"AA000062"}, {"id":70,"name":"Compute XLarge PRD","displaytext":"8CPU, 13.6GB RAM, 160GB Storage","cpunumber":8,"cpuspeed":1200,"memory":13928,"created":"2011-02-08T07:06:19+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":69,"name":"Compute Large PRD","displaytext":"4CPU, 6.8GB RAM, 160GB Storage","cpunumber":4,"cpuspeed":1200,"memory":6964,"created":"2011-02-08T07:05:47+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":68,"name":"Compute Medium PRD","displaytext":"2CPU, 3.4GB RAM, 160GB Storage","cpunumber":2,"cpuspeed":1200,"memory":3484,"created":"2011-02-08T07:05:03+0000","storagetype":"shared","offerha":true,"domainid":14,"do
main":"AA000062"}, {"id":67,"name":"Compute Small PRD","displaytext":"1CPU, 1.7GB RAM, 160GB Storage","cpunumber":1,"cpuspeed":1200,"memory":1744,"created":"2011-02-08T07:03:44+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listTemplates_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listTemplates_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listTemplates_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listTemplates_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listtemplatesresponse" : { "template" : [ {"id":576,"name":"ESX[beta] Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","displaytext":"ESX[beta] Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","ispublic":true,"created":"2011-06-01T01:25:12+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":126,"ostypename":"Ubuntu 10.04 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":702743552,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":443,"name":"XEN Basic Windows Svr 2008 R2 x64 R2.1","displaytext":"XEN Basic Windows Svr 2008 R2 x64 R2.1","ispublic":true,"created":"2011-03-25T01:29:46+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":54,"ostypename":"Windows Server 2008 R2 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","doma
in":"ROOT","domainid":1,"isextractable":false}, {"id":474,"name":"XEN Basic Windows Svr 2003 SP2 STD","displaytext":"XEN Basic Windows Svr 2003 SP2 STD","ispublic":true,"created":"2011-04-07T10:38:45+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":89,"ostypename":"Windows Server 2003 Standard Edition(32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":444,"name":"ESX[beta] Windows 2003 x32 R2.0","displaytext":"ESX[beta] Windows 2003 x32 R2.0","ispublic":true,"created":"2011-03-25T01:34:00+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":89,"ostypename":"Windows Server 2003 Standard Edition(32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":876909056,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domai
nid":1,"isextractable":false}, {"id":447,"name":"ESX[beta] Windows 2008 x32 R2.0","displaytext":"ESX[beta] Windows 2008 x32 R2.0","ispublic":true,"created":"2011-03-25T01:45:23+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":52,"ostypename":"Windows Server 2008 (32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":3391547904,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":462,"name":"ESX[beta] Centos 5.5 x64 R2.0","displaytext":"ESX[beta] Centos 5.5 x64 R2.0","ispublic":true,"created":"2011-03-28T05:06:36+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":2263178240,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":425,"name":"XEN Windows 2008 x32 R2
.0","displaytext":"XEN Windows 2008 x32 R2.0","ispublic":true,"created":"2011-03-22T03:22:21+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":52,"ostypename":"Windows Server 2008 (32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":461,"name":"ESX[beta] Basic Windows 2008 R2 x64","displaytext":"ESX[beta] Basic Windows 2008 R2 x64","ispublic":true,"created":"2011-03-26T22:48:48+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":54,"ostypename":"Windows Server 2008 R2 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":3230146048,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":575,"name":"Xen Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","displaytext":"Xen Ubuntu 10
.04.2 CHEF Small \\ Micro Optimised","ispublic":true,"created":"2011-06-01T01:06:21+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":85899345920,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":481,"name":"XEN Centos 5.4 x64 R2.0","displaytext":"XEN Centos 5.4 x64 R2.0","ispublic":true,"created":"2011-04-14T01:43:49+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171966464000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":421,"name":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","displaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","ispublic":true,"created":"
2011-03-22T02:54:06+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":167772160000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":423,"name":"XEN Basic Centos 5.5 x64 PV r2.2","displaytext":"XEN Basic Centos 5.5 x64 PV r2.2","ispublic":true,"created":"2011-03-22T02:59:31+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":167772160000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":422,"name":"XEN OpenSUSE x64 11.4 R2.0","displaytext":"XEN OpenSUSE x64 11.4 R2.0","ispublic":true,"created":"2011-03-22T02:58:25+0000","isready":true,"passwordenabled":false,"format":"
VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171966464000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listVirtualMachines_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listVirtualMachines_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listVirtualMachines_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listVirtualMachines_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listvirtualmachinesresponse" : { "virtualmachine" : [ {"id":2600,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:06:42+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"1.78%","networkkbsread":2,"networkkbswrite":2,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3891,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.116","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}, {"id":2601,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libclo
ud-dev","created":"2011-06-23T05:09:44+0000","state":"Starting","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"jobid":17147,"jobstatus":0,"nic":[{"id":3892,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.203","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listZones_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listZones_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listZones_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listZones_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail2.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail2.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail2.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/listZones_deployfail2.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17164,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17165,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Destroyed","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17177,"jobstatus":2} }
Added: libcloud/trunk/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json (added)
+++ libcloud/trunk/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "rebootvirtualmachineresponse" : {"jobid":17165} }
Added: libcloud/trunk/test/compute/test_cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/test_cloudstack.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/compute/test_cloudstack.py (added)
+++ libcloud/trunk/test/compute/test_cloudstack.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,88 @@
+import httplib
+import sys
+import unittest
+import urlparse
+
+try:
+ import json
+except:
+ import simplejson as json
+
+from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver
+from libcloud.compute.types import DeploymentError
+
+from test import MockHttpTestCase
+from test.compute import TestCaseMixin
+from test.file_fixtures import ComputeFileFixtures
+
+class CloudStackNodeDriverTest(unittest.TestCase, TestCaseMixin):
+ def setUp(self):
+ CloudStackNodeDriver.connectionCls.conn_classes = \
+ (None, CloudStackMockHttp)
+ self.driver = CloudStackNodeDriver('apikey', 'secret')
+ self.driver.path = '/test/path'
+ self.driver.type = -1
+ CloudStackMockHttp.fixture_tag = 'default'
+
+ def test_create_node_immediate_failure(self):
+ size = self.driver.list_sizes()[0]
+ image = self.driver.list_images()[0]
+ CloudStackMockHttp.fixture_tag = 'deployfail'
+ try:
+ node = self.driver.create_node(name='node-name',
+ image=image,
+ size=size)
+ except:
+ return
+ self.assertTrue(False)
+
+ def test_create_node_delayed_failure(self):
+ size = self.driver.list_sizes()[0]
+ image = self.driver.list_images()[0]
+ CloudStackMockHttp.fixture_tag = 'deployfail2'
+ try:
+ node = self.driver.create_node(name='node-name',
+ image=image,
+ size=size)
+ except:
+ return
+ self.assertTrue(False)
+
+class CloudStackMockHttp(MockHttpTestCase):
+ fixtures = ComputeFileFixtures('cloudstack')
+ fixture_tag = 'default'
+
+ def _load_fixture(self, fixture):
+ body = self.fixtures.load(fixture)
+ return body, json.loads(body)
+
+ def _test_path(self, method, url, body, headers):
+ url = urlparse.urlparse(url)
+ query = dict(urlparse.parse_qsl(url.query))
+
+ self.assertTrue('apiKey' in query)
+ self.assertTrue('command' in query)
+ self.assertTrue('response' in query)
+ self.assertTrue('signature' in query)
+
+ self.assertTrue(query['response'] == 'json')
+
+ del query['apiKey']
+ del query['response']
+ del query['signature']
+ command = query.pop('command')
+
+ if hasattr(self, '_cmd_' + command):
+ return getattr(self, '_cmd_' + command)(**query)
+ else:
+ fixture = command + '_' + self.fixture_tag + '.json'
+ body, obj = self._load_fixture(fixture)
+ return (httplib.OK, body, obj, httplib.responses[httplib.OK])
+
+ def _cmd_queryAsyncJobResult(self, jobid):
+ fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json'
+ body, obj = self._load_fixture(fixture)
+ return (httplib.OK, body, obj, httplib.responses[httplib.OK])
+
+if __name__ == '__main__':
+ sys.exit(unittest.main())
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "assigntoloadbalancerruleresponse" : {"jobid":17341} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "associateipaddressresponse" : {"jobid":17346,"id":34000} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "createloadbalancerruleresponse" : { "loadbalancer" : {"id":2253,"name":"fake","publicipid":34000,"publicip":"1.1.1.49","publicport":"80","privateport":"80","algorithm":"roundrobin","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","state":"Add"} } }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "deleteloadbalancerruleresponse" : {"jobid":17342} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "disassociateipaddressresponse" : {"jobid":17344} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listloadbalancerruleinstancesresponse" : { "loadbalancerruleinstance" : [ {"id":2614,"name":"test_1308874974","displayname":"test_1308874974","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-24T00:22:56+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":2185,"networkkbswrite":109,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3914,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.3.122","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}, {"id":2615,"name":"test_1308875456","displayname":"test_1308875
456","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-24T00:30:57+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":1118,"networkkbswrite":75,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3915,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.2.62","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"} ] } }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listloadbalancerrulesresponse" : { "loadbalancerrule" : [ {"id":2247,"name":"test","publicipid":34000,"publicip":"1.1.1.49","publicport":"80","privateport":"80","algorithm":"roundrobin","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","state":"Active"},{"id":2249,"name":"testmore","publicipid":34001,"publicip":"1.1.2.49","publicport":"80","privateport":"80","algorithm":"leastconn","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","state":"Active"} ] } }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listZones_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listZones_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listZones_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/listZones_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17340,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17341,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17342,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17344,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"jobid":17346,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"ipaddress":{"id":34000,"ipaddress":"1.1.1.49","allocated":"2011-06-24T05:52:55+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocating"}}} }
Added: libcloud/trunk/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json (added)
+++ libcloud/trunk/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json Thu Jun 30 12:26:18 2011
@@ -0,0 +1 @@
+{ "removefromloadbalancerruleresponse" : {"jobid":17340} }
Added: libcloud/trunk/test/loadbalancer/test_cloudstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/test_cloudstack.py?rev=1141506&view=auto
==============================================================================
--- libcloud/trunk/test/loadbalancer/test_cloudstack.py (added)
+++ libcloud/trunk/test/loadbalancer/test_cloudstack.py Thu Jun 30 12:26:18 2011
@@ -0,0 +1,95 @@
+import httplib
+import sys
+import unittest
+import urlparse
+
+try:
+ import json
+except:
+ import simplejson as json
+
+from libcloud.common.types import LibcloudError
+from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm
+from libcloud.loadbalancer.drivers.cloudstack import CloudStackLBDriver
+
+from test import MockHttpTestCase
+from test.file_fixtures import LoadBalancerFileFixtures
+
+class CloudStackLBTests(unittest.TestCase):
+ def setUp(self):
+ CloudStackLBDriver.connectionCls.conn_classes = \
+ (None, CloudStackMockHttp)
+ self.driver = CloudStackLBDriver('apikey', 'secret')
+ self.driver.path = '/test/path'
+ self.driver.type = -1
+ self.driver.name = 'CloudStack'
+ CloudStackMockHttp.fixture_tag = 'default'
+
+ def test_list_balancers(self):
+ balancers = self.driver.list_balancers()
+ for balancer in balancers:
+ self.assertTrue(isinstance(balancer, LoadBalancer))
+
+ def test_create_balancer(self):
+ members = [Member(1, '1.1.1.1', 80), Member(2, '1.1.1.2', 80)]
+ balancer = self.driver.create_balancer('fake', members)
+ self.assertTrue(isinstance(balancer, LoadBalancer))
+
+ def test_destroy_balancer(self):
+ balancer = self.driver.list_balancers()[0]
+ self.driver.destroy_balancer(balancer)
+
+ def test_balancer_attach_member(self):
+ balancer = self.driver.list_balancers()[0]
+ member = Member(id=1234, ip='1.1.1.1', port=80)
+ balancer.attach_member(member)
+
+ def test_balancer_detach_member(self):
+ balancer = self.driver.list_balancers()[0]
+ member = balancer.list_members()[0]
+ balancer.detach_member(member)
+
+ def test_balancer_list_members(self):
+ balancer = self.driver.list_balancers()[0]
+ members = balancer.list_members()
+ for member in members:
+ self.assertTrue(isinstance(member, Member))
+
+class CloudStackMockHttp(MockHttpTestCase):
+ fixtures = LoadBalancerFileFixtures('cloudstack')
+ fixture_tag = 'default'
+
+ def _load_fixture(self, fixture):
+ body = self.fixtures.load(fixture)
+ return body, json.loads(body)
+
+ def _test_path(self, method, url, body, headers):
+ url = urlparse.urlparse(url)
+ query = dict(urlparse.parse_qsl(url.query))
+
+ self.assertTrue('apiKey' in query)
+ self.assertTrue('command' in query)
+ self.assertTrue('response' in query)
+ self.assertTrue('signature' in query)
+
+ self.assertTrue(query['response'] == 'json')
+
+ del query['apiKey']
+ del query['response']
+ del query['signature']
+ command = query.pop('command')
+
+ if hasattr(self, '_cmd_' + command):
+ return getattr(self, '_cmd_' + command)(**query)
+ else:
+ fixture = command + '_' + self.fixture_tag + '.json'
+ body, obj = self._load_fixture(fixture)
+ return (httplib.OK, body, obj, httplib.responses[httplib.OK])
+
+ def _cmd_queryAsyncJobResult(self, jobid):
+ fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json'
+ body, obj = self._load_fixture(fixture)
+ return (httplib.OK, body, obj, httplib.responses[httplib.OK])
+
+if __name__ == "__main__":
+ sys.exit(unittest.main())