From 5db520ad107d81aeb0e2dcad67aab4f8d52a34a5 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Fri, 6 May 2011 11:05:57 +0100 Subject: [PATCH 01/55] Remove list_deleted since this is not exposed anymore. --- README.html | 22 +++++++------- README.rst | 11 ------- bin/cloudlb | 65 +++++++++++++++++++--------------------- cloudlb/loadbalancers.py | 10 ------- tests/test.sh | 3 -- 5 files changed, 43 insertions(+), 68 deletions(-) diff --git a/README.html b/README.html index e1aadc3..f750584 100644 --- a/README.html +++ b/README.html @@ -221,23 +221,25 @@

Usage

lb = clb.loadbalancers.get(LoadBalancerID) lb.delete() -

List deleted LBs:

+

List nodes of a LB:

 #!/usr/bin/python
 import cloudlb
 clb = cloudlb.CloudLoadBalancer("username", "apikey","chicago")
 
-lbs = clb.loadbalancers.list_deleted()
-for x in lbs:
-    print x.name
+lbs = clb.loadbalancers.list()
+lb = lbs[0] #get the first one
+nodes=lb.nodes.filter(status='ENABLED')
+for node in nodes:
+    print node.address
 
-

List nodes of a LB:

+

Filter nodes via condition of a LB:

 #!/usr/bin/python
 import cloudlb
 clb = cloudlb.CloudLoadBalancer("username", "apikey","chicago")
 
-lbs = clb.loadbalancers.list_deleted()
+lbs = clb.loadbalancers.list()
 lb = lbs[0] #get the first one
 for node in lb.nodes:
     print node.address
@@ -403,7 +405,7 @@ 

Usage

timeout=10, attemptsBeforeDeactivation=3, path="/", - statusRegex="", + statusRegex="^[234][0-9][0-9]$", bodyRegex="testing") hm_monitor.add(hm)
@@ -433,7 +435,7 @@

Usage

ssp = mylb.session_persistense() ssp.add(ss) -

Get session persistense:

+

Get session persistence:

 #!/usr/bin/python
 import cloudlb
@@ -501,8 +503,8 @@ 

Usage

# Delete all accesslist accesslist.delete() -# Delete accesslist by ID (TODO: Not working ATM) -# accesslist.delete(id=62) +# Delete accesslist by ID +accesslist.delete(id=62)
diff --git a/README.rst b/README.rst index 055b8b8..df4f7d5 100644 --- a/README.rst +++ b/README.rst @@ -48,17 +48,6 @@ List LoadBalancers:: for ip in lb.virtualIps: print "%s/%s" % (ip.ipVersion, ip.address) -List deleted LoadBalancers:: - - #!/usr/bin/python - import cloudlb - clb = cloudlb.CloudLoadBalancer("username", "apikey","chicago") - - lbs = clb.loadbalancers.list_deleted() - for x in lbs: - print x.name - - Get LB by ID:: #!/usr/bin/python diff --git a/bin/cloudlb b/bin/cloudlb index eb38c30..e469747 100755 --- a/bin/cloudlb +++ b/bin/cloudlb @@ -142,40 +142,37 @@ class CLBCli(object): def list_loadbalancers(self, args): self._get_connexion() - if len(args) >= 1 and args[0] == "deleted": - lbs = self.cnx.loadbalancers.list_deleted() - else: - lbs = self.cnx.loadbalancers.list() - if len(args) >= 1: - filtered_lbs = [] - allowed_variables = ['id', - 'port', - 'protocol', - 'name', - 'status', - 'address', - ] - config = self._parse_variables_args(allowed_variables, args) - for d in lbs: - if 'id' in config and int(d.id) == int(config['id']): - filtered_lbs.append(d) - elif 'port' in config and \ - int(d.port) == int(config['port']): - filtered_lbs.append(d) - elif 'protocol' in config and \ - d.protocol.lower() == config['protocol'].lower(): - filtered_lbs.append(d) - elif 'name' in config and \ - d.name.lower() == config['name'].lower(): - filtered_lbs.append(d) - elif 'status' in config and \ - d.status.lower() == config['status'].lower(): - filtered_lbs.append(d) - elif 'address' in config: - for ip in d.virtualIps: - if ip.address == config['address'].lower(): - filtered_lbs.append(d) - lbs = filtered_lbs + lbs = self.cnx.loadbalancers.list() + if len(args) >= 1: + filtered_lbs = [] + allowed_variables = ['id', + 'port', + 'protocol', + 'name', + 'status', + 'address', + ] + config = self._parse_variables_args(allowed_variables, args) + for d in lbs: + if 'id' in config and int(d.id) == int(config['id']): + filtered_lbs.append(d) + elif 'port' in config and \ + int(d.port) == int(config['port']): + filtered_lbs.append(d) + elif 'protocol' in config and \ + d.protocol.lower() == config['protocol'].lower(): + filtered_lbs.append(d) + elif 'name' in config and \ + d.name.lower() == config['name'].lower(): + filtered_lbs.append(d) + elif 'status' in config and \ + d.status.lower() == config['status'].lower(): + filtered_lbs.append(d) + elif 'address' in config: + for ip in d.virtualIps: + if ip.address == config['address'].lower(): + filtered_lbs.append(d) + lbs = filtered_lbs for lb in lbs: pvip = [] diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 306debb..5429f43 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -109,16 +109,6 @@ def list(self): self._list("/loadbalancers.json", "loadBalancers") \ if x._info['status'] != "DELETED"] - def list_deleted(self): - """ - Get a list of deleted loadbalancers. - :rtype: list of :class:`LoadBalancer` - - Arguments: - """ - return [x for x in self._list("/loadbalancers.json", "loadBalancers") \ - if x._info['status'] == "DELETED"] - def create(self, name, port, protocol, nodes, virtualIps): """ diff --git a/tests/test.sh b/tests/test.sh index 3959022..d2b1bce 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -18,9 +18,6 @@ ${A} create loadbalancer \ # List all LoadBalancers $A list loadbalancers >/dev/null -# List all deleted Loadbalancers -$A list loadbalancers deleted >/dev/null - # List filtering by LBTEST=$(${A} list loadbalancers name=$LBNAME|head -1|sed 's/ID: //;s/,.*//') From fdb38e0b35e91bfa2a6f2d420b8c5328a1835806 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Fri, 6 May 2011 11:06:58 +0100 Subject: [PATCH 02/55] Don't set HTTP_COOKIE statically. even if it's the method at this time, we may have different ones in the future. --- bin/cloudlb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/cloudlb b/bin/cloudlb index e469747..ba6ed90 100755 --- a/bin/cloudlb +++ b/bin/cloudlb @@ -524,7 +524,7 @@ class CLBCli(object): loadbalancer = self._get_loadbalancer(loadbalancer) ss = cloudlb.sessionpersistence.SessionPersistence( - persistenceType="HTTP_COOKIE") + persistenceType=session_persistence_type) ssp = loadbalancer.session_persistence() ssp.add(ss) From 66026df9456785814f0355f31b059e8adc71fe08 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Fri, 6 May 2011 12:19:00 +0100 Subject: [PATCH 03/55] Fix test of settings healthmonitor to HTTPS. Loadbalancer protocol needs to be HTTPS before healthmonitor is HTTPS. --- tests/test.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test.sh b/tests/test.sh index d2b1bce..6e4d323 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -90,15 +90,17 @@ $A -w set healthmonitor ${LBTEST} type="CONNECT" delay="10" timeout="10" attempt # Set healthmonitor to HTTP (need to have path statusRegex and bodyRegex) $A -w set healthmonitor ${LBTEST} type="HTTP" delay="5" timeout="2" attemptsBeforeDeactivation=3 path=/ statusRegex="^[234][0-9][0-9]$" bodyRegex=testing >/dev/null -# Set healthmonitor to HTTPS (need to have path statusRegex and bodyRegex) -# $A -w set healthmonitor ${LBTEST} type="HTTPS" delay="5" timeout="1" attemptsBeforeDeactivation=5 path=/ statusRegex="^[234][0-9][0-9]$" bodyRegex=foobar >/dev/null - # Show healthmonitoring rule. $A -w show healthmonitor ${LBTEST} >/dev/null # Delete healthmonitorring $A -w delete healthmonitor ${LBTEST} >/dev/null +# Set healthmonitor to HTTPS (need to have path statusRegex and bodyRegex) +$A -w set loadbalancer ${LBTEST} protocol=HTTPS >/dev/null +$A -w set healthmonitor ${LBTEST} type="HTTPS" delay="5" timeout="1" attemptsBeforeDeactivation=5 path=/ statusRegex="^[234][0-9][0-9]$" bodyRegex=foobar >/dev/null >/dev/null +$A -w delete healthmonitor ${LBTEST} >/dev/null + ### LoadBalancer attribute # Update LoadBalancer attribute (1) From 5017815aa287b48e16d035525537106911584568 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Fri, 6 May 2011 12:25:08 +0100 Subject: [PATCH 04/55] Improve debugging. --- cloudlb/client.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 5bbd95b..641b17e 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -73,15 +73,13 @@ def _cloudlb_request(self, url, method, **kwargs): fullurl = "%s%s%s" % (self.region_account_url, url, ext) #DEBUGGING: - if 'PYTHON_CLOUDB_DEBUG' in os.environ: - sys.stderr.write("URL: %s" % (fullurl)) - sys.stderr.write("ARGS: %s" % (str(kwargs))) - sys.stderr.write("METHOD: %s" % (str(method))) + if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + sys.stderr.write("URL: %s\n" % (fullurl)) + sys.stderr.write("ARGS: %s\n" % (str(kwargs))) + sys.stderr.write("METHOD: %s\n" % (str(method))) if 'body' in kwargs: from pprint import pprint as p - p("BODY: %s" % kwargs['body'], - stream=sys.stderr) - + p(json.loads(kwargs['body'])) response, body = self.request(fullurl, method, **kwargs) if body: From f0643d0f52e9a96ab918123b2092b760ba65e115 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Fri, 6 May 2011 12:30:38 +0100 Subject: [PATCH 05/55] 0.3 --- cloudlb/consts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/consts.py b/cloudlb/consts.py index ddeba6d..636fd5a 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -1,6 +1,6 @@ # -*- encoding: utf-8 -*- __author__ = "Chmouel Boudjnah " -VERSION = "0.2" +VERSION = "0.3" USER_AGENT = 'python-cloudb/%s' % VERSION # Default AUTH SERVER From e4da6d0c11810ccc7af5d9b34d68dc391b9daeee Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Thu, 7 Jul 2011 16:39:17 +0100 Subject: [PATCH 06/55] Add UK support. --- cloudlb/client.py | 7 ++++++- cloudlb/consts.py | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 641b17e..4b79c20 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -18,10 +18,15 @@ def __init__(self, username, api_key, region, - auth_url=cloudlb.consts.DEFAULT_AUTH_SERVER): + auth_url=None): super(CLBClient, self).__init__() self.username = username self.api_key = api_key + + if not auth_url and region == 'lon': + auth_url = cloudlb.consts.UK_AUTH_SERVER + else: + auth_url = cloudlb.consts.DEFAULT_AUTH_SERVER self._auth_url = auth_url if region.lower() in cloudlb.consts.REGION.values(): diff --git a/cloudlb/consts.py b/cloudlb/consts.py index 636fd5a..c9c3595 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -6,6 +6,9 @@ # Default AUTH SERVER DEFAULT_AUTH_SERVER = "https://auth.api.rackspacecloud.com/v1.0" +# UK AUTH SERVER +UK_AUTH_SERVER = "https://lon.auth.api.rackspacecloud.com/v1.0" + # Default URL for Regions REGION_URL = "https://%s.loadbalancers.api.rackspacecloud.com/v1.0" @@ -13,6 +16,7 @@ REGION = { "chicago": "ord", "dallas": "dfw", + "london": "lon", } # Allowed Protocol From 708cb630b2dc0ec60243041626759e743f4904be Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Thu, 7 Jul 2011 16:39:40 +0100 Subject: [PATCH 07/55] 0.4 release. --- cloudlb/consts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/consts.py b/cloudlb/consts.py index c9c3595..b967116 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -1,6 +1,6 @@ # -*- encoding: utf-8 -*- __author__ = "Chmouel Boudjnah " -VERSION = "0.3" +VERSION = "0.4" USER_AGENT = 'python-cloudb/%s' % VERSION # Default AUTH SERVER From c380ad44a6d31293e59396bc22cc3390c693e49e Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Wed, 27 Jul 2011 14:54:18 -0400 Subject: [PATCH 08/55] Added dictionary conversion to str --- cloudlb/loadbalancers.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 5429f43..ea8b443 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -39,7 +39,15 @@ def _add_details(self, info): v = v['name'] if k == "virtualIps": - v = [VirtualIP(parent=self, **x) for x in v] + nv = [] + + for x in v: + tmp_dict = {} + for k,y in x.items(): + tmp_dict[str(k)] = y + nv.append(tmp_dict) + + v = [VirtualIP(parent=self, **x) for x in nv] if k in ('created', 'updated'): v = base.convert_iso_datetime(v['time']) From 46286021a2ef6f87137372304d9b6a41c8fe2687 Mon Sep 17 00:00:00 2001 From: Yaniv Aknin Date: Wed, 5 Oct 2011 10:03:44 +0200 Subject: [PATCH 09/55] make client.py always return dicts with string keys By default, json.loads() returns only unicode strings. Since we later try to use these dicts as **kwargs, and since Python 2.6 doesn't like unicode keyword arguments, things break. This patch adds an object_hook parameter to json.loads, so that all dicts generated by json.loads will have explicit string keys. --- cloudlb/client.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 4b79c20..4b1a96d 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -8,7 +8,6 @@ import cloudlb.consts import cloudlb.errors - class CLBClient(httplib2.Http): """ Client class for accessing the CLB API. @@ -89,7 +88,7 @@ def _cloudlb_request(self, url, method, **kwargs): if body: try: - body = json.loads(body) + body = json.loads(body, object_hook=lambda obj: dict((k.encode('ascii'), v) for k, v in obj.items())) except(ValueError): pass From dbbf3eedd2002f3ae3b888f9ef2ac84d0e896c3a Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Thu, 29 Dec 2011 15:23:18 -0600 Subject: [PATCH 10/55] Add body response to debug output. --- cloudlb/client.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 4b79c20..d079b31 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -4,6 +4,7 @@ import os import sys import json +import pprint import cloudlb.consts import cloudlb.errors @@ -79,12 +80,12 @@ def _cloudlb_request(self, url, method, **kwargs): #DEBUGGING: if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + pp = pprint.PrettyPrinter(stream=sys.stderr, indent=2) sys.stderr.write("URL: %s\n" % (fullurl)) sys.stderr.write("ARGS: %s\n" % (str(kwargs))) sys.stderr.write("METHOD: %s\n" % (str(method))) if 'body' in kwargs: - from pprint import pprint as p - p(json.loads(kwargs['body'])) + pp.printp(json.loads(kwargs['body'])) response, body = self.request(fullurl, method, **kwargs) if body: @@ -93,6 +94,10 @@ def _cloudlb_request(self, url, method, **kwargs): except(ValueError): pass + if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + sys.stderr.write("BODY:") + pp.pprint(body) + if (response.status < 200) or (response.status > 299): raise cloudlb.errors.ResponseError(response.status, response.reason) From 34c2de3370340290f894a6e3a7c1a4b09db0a509 Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Sun, 22 Jan 2012 19:44:45 -0600 Subject: [PATCH 11/55] Previous commit had a prettyprint typo. --- cloudlb/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index d079b31..24dcc57 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -85,7 +85,7 @@ def _cloudlb_request(self, url, method, **kwargs): sys.stderr.write("ARGS: %s\n" % (str(kwargs))) sys.stderr.write("METHOD: %s\n" % (str(method))) if 'body' in kwargs: - pp.printp(json.loads(kwargs['body'])) + pp.pprint(json.loads(kwargs['body'])) response, body = self.request(fullurl, method, **kwargs) if body: From 35f24d7fe6189ec5da94a51bde5c8e2cf4df43a7 Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Sun, 22 Jan 2012 20:00:02 -0600 Subject: [PATCH 12/55] Initial custom error page support. --- README.rst | 19 +++++++++++++++++++ cloudlb/errorpage.py | 25 +++++++++++++++++++++++++ cloudlb/loadbalancers.py | 6 +++++- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 cloudlb/errorpage.py diff --git a/README.rst b/README.rst index df4f7d5..b998a57 100644 --- a/README.rst +++ b/README.rst @@ -352,6 +352,25 @@ Access Lists:: # Delete accesslist by ID accesslist.delete(id=62) +Custom Error Page:: + + #!/usr/bin/python + import cloudlb + clb = cloudlb.CloudLoadBalancer("username", "apikey","chicago") + + lbs = clb.loadbalancers.list() + mylb = lbs[0] #first lb + errorpage = mylb.errorpage() + + # Display current error page + print errorpage.get() + + # Change the error page + errorpage.add('

Error

') + + # Revert to the default error page + errorpage.delete() + LICENSE ======= diff --git a/cloudlb/errorpage.py b/cloudlb/errorpage.py new file mode 100644 index 0000000..074c5dd --- /dev/null +++ b/cloudlb/errorpage.py @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +__author__ = "Chmouel Boudjnah " + +class ErrorPage(object): + def __repr__(self): + return "" + + def __init__(self, client, lbId=None): + self.lbId = lbId + if self.lbId: + self.lbId = int(self.lbId) + self.path = "/loadbalancers/%s/errorpage" % self.lbId + + self.client = client + + def get(self): + ret = self.client.get("%s.json" % self.path) + return ret[1]['errorpage']['content'] + + def add(self, html): + body = {'errorpage': {'content': html}} + self.client.put(self.path, body=body) + + def delete(self): + self.client.delete(self.path) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index ea8b443..de1c115 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -11,7 +11,7 @@ from cloudlb.sessionpersistence import SessionPersistenceManager from cloudlb.connectionlogging import ConnectionLogging from cloudlb.connectionthrottle import ConnectionThrottleManager - +from cloudlb.errorpage import ErrorPage class LoadBalancer(base.Resource): accessList = None @@ -80,6 +80,10 @@ def session_persistence(self): self.manager.api.client, base.getid(self)) return sm + def errorpage(self): + errorpage = ErrorPage(self.manager.api.client, base.getid(self)) + return errorpage + def connection_logging(self): cm = ConnectionLogging( self.manager.api.client, base.getid(self)) From a3364435b6576b7d335d9d153ebc328d64852ebb Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Mon, 23 Jan 2012 00:47:54 -0600 Subject: [PATCH 13/55] Switch to Auth API v1.1 --- cloudlb/client.py | 13 ++++++++----- cloudlb/consts.py | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 24dcc57..e3bec8c 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -42,21 +42,24 @@ def __init__(self, self.region_account_url = None def authenticate(self): - headers = {'X-Auth-User': self.username, 'X-Auth-Key': self.api_key} - response, body = self.request(self._auth_url, 'GET', headers=headers) + headers={'Content-Type': 'application/json'} + body = '{"credentials": {"username": "%s", "key": "%s"}}' % (self.username, self.api_key) + response, body = self.request(self._auth_url, 'POST', body=body, headers=headers) + + auth_data = json.loads(body)['auth'] # A status code of 401 indicates that the supplied credentials # were not accepted by the authentication service. if response.status == 401: raise cloudlb.errors.AuthenticationFailed() - if response.status != 204: + if response.status != 200: raise cloudlb.errors.ResponseError(response.status, response.reason) self.account_number = int(os.path.basename( - response['x-server-management-url'])) - self.auth_token = response['x-auth-token'] + auth_data['serviceCatalog']['cloudServers'][0]['publicURL'])) + self.auth_token = auth_data['token']['id'] self.region_account_url = "%s/%s" % ( cloudlb.consts.REGION_URL % (self.region), self.account_number) diff --git a/cloudlb/consts.py b/cloudlb/consts.py index b967116..4325462 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -4,10 +4,10 @@ USER_AGENT = 'python-cloudb/%s' % VERSION # Default AUTH SERVER -DEFAULT_AUTH_SERVER = "https://auth.api.rackspacecloud.com/v1.0" +DEFAULT_AUTH_SERVER = "https://auth.api.rackspacecloud.com/v1.1/auth" # UK AUTH SERVER -UK_AUTH_SERVER = "https://lon.auth.api.rackspacecloud.com/v1.0" +UK_AUTH_SERVER = "https://lon.auth.api.rackspacecloud.com/v1.1/auth" # Default URL for Regions REGION_URL = "https://%s.loadbalancers.api.rackspacecloud.com/v1.0" From 6057c72828162e570010d9a1c59e4c0da962b6e3 Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Mon, 23 Jan 2012 01:00:47 -0600 Subject: [PATCH 14/55] Changed title in README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index b998a57..7d188f8 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ ================================================================== - Python interface to Rackspace Load Balancer as a Service product + Python interface to Rackspace Cloud Load Balancers ================================================================== :Homepage: https://github.com/chmouel/python-cloudlb From 51dd56a4d02480d1fea4b1e4df33dc1ea877aa43 Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Sat, 28 Jan 2012 11:18:41 -0600 Subject: [PATCH 15/55] Revert "Added dictionary conversion to str" This reverts commit c380ad44a6d31293e59396bc22cc3390c693e49e. Fixes issue #7. --- cloudlb/loadbalancers.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index de1c115..27ba895 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -39,15 +39,7 @@ def _add_details(self, info): v = v['name'] if k == "virtualIps": - nv = [] - - for x in v: - tmp_dict = {} - for k,y in x.items(): - tmp_dict[str(k)] = y - nv.append(tmp_dict) - - v = [VirtualIP(parent=self, **x) for x in nv] + v = [VirtualIP(parent=self, **x) for x in v] if k in ('created', 'updated'): v = base.convert_iso_datetime(v['time']) From f0b441a4a4c851463502f829a3ea9f75becc9d5d Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Sat, 28 Jan 2012 11:22:00 -0600 Subject: [PATCH 16/55] Added TCP support. Fixes issue #8. --- cloudlb/consts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/consts.py b/cloudlb/consts.py index 4325462..4b649a1 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -22,7 +22,7 @@ # Allowed Protocol LB_PROTOCOLS = ["FTP", "HTTP", "IMAPv4", "POP3", "LDAP", "LDAPS", "HTTPS", "IMAPS", - "POP3S", "SMTP"] + "POP3S", "SMTP", "TCP"] # Attributed allowed to be modified on loadbalancers LB_ATTRIBUTES_MODIFIABLE = ["name", "algorithm", "protocol", "port"] From 69d05564bcea8d2c90200b2e452288fbd4998252 Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Sun, 29 Jan 2012 13:50:23 -0600 Subject: [PATCH 17/55] Add load balancer search for specific IP. Fixes #11. --- README.rst | 11 +++++++++++ cloudlb/loadbalancers.py | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/README.rst b/README.rst index 7d188f8..3219d88 100644 --- a/README.rst +++ b/README.rst @@ -48,6 +48,17 @@ List LoadBalancers:: for ip in lb.virtualIps: print "%s/%s" % (ip.ipVersion, ip.address) +List LoadBalancers who have nodes that belong to it:: + + #!/usr/bin/python + import cloudlb + clb = cloudlb.CloudLoadBalancer("username", "apikey","chicago") + + ip = '10.1.1.1' + lbs = clb.loadbalancers.search(ip) + for lb in lbs: + print "%s has %s node attached" % (lb.name, ip)) + Get LB by ID:: #!/usr/bin/python diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 27ba895..4e0eca1 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -113,6 +113,17 @@ def list(self): self._list("/loadbalancers.json", "loadBalancers") \ if x._info['status'] != "DELETED"] + def search(self, ip): + """ + Get a list of loadbalancers who are balancing traffic to `ip`. + The loadbalancer details are not as complete as the list() call, + only name, status and id are returned. + """ + return [x for x in \ + self._list("/loadbalancers.json?nodeaddress=%s" % ip, + "loadBalancers")] + + def create(self, name, port, protocol, nodes, virtualIps): """ From 01ba2ebb85c936b8dd5f1da2f85aa8a1145ee42d Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Sun, 29 Jan 2012 14:19:56 -0600 Subject: [PATCH 18/55] Add real-time statistics support. Fixes #12. --- README.rst | 11 +++++++++++ cloudlb/loadbalancers.py | 5 +++++ cloudlb/stats.py | 17 +++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 cloudlb/stats.py diff --git a/README.rst b/README.rst index 3219d88..2319e06 100644 --- a/README.rst +++ b/README.rst @@ -192,6 +192,17 @@ Get usage statitiscs on a specfic LoadBalancer:: print mylb.get_usage() +Get real-time statistics on a specific LoadBalancer:: + + #!/usr/bin/python + import cloudlb + clb = cloudlb.CloudLoadBalancer("username", "apikey","chicago") + + lbs = clb.loadbalancers.list() + mylb = lbs[0] #first lb + + print mylb.get_stats() + Get limits on all LoadBalancers:: #!/usr/bin/python diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 4e0eca1..306286c 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -6,6 +6,7 @@ from cloudlb.node import Node, NodeDict from cloudlb.virtualip import VirtualIP from cloudlb.usage import get_usage +from cloudlb.stats import Stats from cloudlb.accesslist import AccessList from cloudlb.healthmonitor import HealthMonitorManager from cloudlb.sessionpersistence import SessionPersistenceManager @@ -59,6 +60,10 @@ def get_usage(self, startTime=None, endTime=None): startTime=startTime, endTime=endTime) return ret + def get_stats(self): + stats = Stats(self.manager.api.client, base.getid(self)) + return stats.get() + def accesslist(self): accesslist = AccessList(self.manager.api.client, base.getid(self)) return accesslist diff --git a/cloudlb/stats.py b/cloudlb/stats.py new file mode 100644 index 0000000..9aa3731 --- /dev/null +++ b/cloudlb/stats.py @@ -0,0 +1,17 @@ +# -*- encoding: utf-8 -*- +__author__ = "Chmouel Boudjnah " + +class Stats(object): + def __init__(self, client, lbId=None): + self.lbId = lbId + if self.lbId: + self.lbId = int(self.lbId) + self.path = "/loadbalancers/%s/stats" % self.lbId + + self.client = client + + def get(self): + ret = self.client.get("%s.json" % self.path) + #return ret[1]['errorpage']['content'] + return ret[1] + From 4b822bc18d4bdc5ed6e6da0c70e1c462b26edcb1 Mon Sep 17 00:00:00 2001 From: Caleb Groom Date: Sun, 29 Jan 2012 18:16:39 -0600 Subject: [PATCH 19/55] Fixed typo in README --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 2319e06..14541df 100644 --- a/README.rst +++ b/README.rst @@ -173,7 +173,7 @@ Update attributes on LoadBalancer:: mylb.update() -Get usage statitiscs on all LoadBalancers:: +Get usage statistics on all LoadBalancers:: #!/usr/bin/python import cloudlb @@ -181,7 +181,7 @@ Get usage statitiscs on all LoadBalancers:: print clb.get_usage() -Get usage statitiscs on a specfic LoadBalancer:: +Get usage statistics on a specfic LoadBalancer:: #!/usr/bin/python import cloudlb From 26d3fbf79d33e605199ae00f2292a4b79ca33a26 Mon Sep 17 00:00:00 2001 From: Aaron Levy Date: Thu, 2 Feb 2012 14:03:57 -0800 Subject: [PATCH 20/55] Return the api reponse data when adding nodes. --- cloudlb/loadbalancers.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index de1c115..aea52f2 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -55,7 +55,8 @@ def _add_details(self, info): setattr(self, k, v) def add_nodes(self, nodes): - self.manager.add_nodes(self.id, nodes) + resp, body = self.manager.add_nodes(self.id, nodes) + return [Node(parent=self, **x) for x in body['nodes']] def update(self): self.manager.update(self, self._info, self.__dict__) @@ -158,10 +159,12 @@ def delete(self, loadbalancerid): """ self._delete("/loadbalancers/%s" % base.getid(loadbalancerid)) - def add_nodes(self, loadbalancerId, nodes): + def add_nodes(self, loadBalancerId, nodes): nodeDico = [x.toDict() for x in nodes] - self._action('nodes', "%d/nodes" % base.getid(loadbalancerId), \ - nodeDico) + resp, body = self.api.client.post('/loadbalancers/%d/nodes' % ( + base.getid(loadBalancerId) + ), body={"nodes": nodeDico}) + return (resp, body) def delete_node(self, loadBalancerId, nodeId): self.api.client.delete('/loadbalancers/%d/nodes/%d' % ( @@ -191,8 +194,3 @@ def update(self, lb, originalInfo, info): self.api.client.put('/loadbalancers/%s' % base.getid(lb), body=ret) - def _action(self, action, url, info=None): - """ - Perform a loadbalancer POST "action". - """ - self.api.client.post('/loadbalancers/%s' % url, body={action: info}) From 6fac200516cb5bc0d5f86b72675b2b7ac0841c6a Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Wed, 8 Feb 2012 08:54:37 -0600 Subject: [PATCH 21/55] Handle a 413 over limit (with a sane hold time) Fix PEP8 errors in client.py --- cloudlb/client.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index e3bec8c..3287382 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -5,6 +5,8 @@ import sys import json import pprint +import time +import datetime import cloudlb.consts import cloudlb.errors @@ -42,9 +44,11 @@ def __init__(self, self.region_account_url = None def authenticate(self): - headers={'Content-Type': 'application/json'} - body = '{"credentials": {"username": "%s", "key": "%s"}}' % (self.username, self.api_key) - response, body = self.request(self._auth_url, 'POST', body=body, headers=headers) + headers = {'Content-Type': 'application/json'} + body = '{"credentials": {"username": "%s", "key": "%s"}}' \ + % (self.username, self.api_key) + response, body = self.request(self._auth_url, 'POST', + body=body, headers=headers) auth_data = json.loads(body)['auth'] @@ -58,7 +62,7 @@ def authenticate(self): response.reason) self.account_number = int(os.path.basename( - auth_data['serviceCatalog']['cloudServers'][0]['publicURL'])) + auth_data['serviceCatalog']['cloudServers'][0]['publicURL'])) self.auth_token = auth_data['token']['id'] self.region_account_url = "%s/%s" % ( cloudlb.consts.REGION_URL % (self.region), @@ -91,6 +95,23 @@ def _cloudlb_request(self, url, method, **kwargs): pp.pprint(json.loads(kwargs['body'])) response, body = self.request(fullurl, method, **kwargs) + # If we hit a 413 (Request Limit) response code, + # check to see how long we have to wait. + # If you have to wait more then 10 seconds, + # raise ResponseError with a more sane message then CLB provides + if response.status == 413: + now = datetime.datetime.strptime(response['date'], + '%a, %d %b %Y %H:%M:%S %Z') + retry = datetime.datetime.strptime(response['retry-after'], + '%a, %d %b %Y %H:%M:%S %Z') + if (retry - now) > datetime.timedelta(seconds=10): + raise cloudlb.errors.ResponseError(response.status, + "Account is currently above limit, please wait " + + (retry - now) + ".") + else: + time.sleep((retry - now).seconds) + response, body = self.request(fullurl, method, **kwargs) + if body: try: body = json.loads(body) From f87988f303dbcfc4517416a52f60295152bd993c Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Wed, 8 Feb 2012 10:07:06 -0600 Subject: [PATCH 22/55] Add a sane Error Message to 413s after the hold-back time --- cloudlb/client.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 3287382..b73702d 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -122,7 +122,11 @@ def _cloudlb_request(self, url, method, **kwargs): sys.stderr.write("BODY:") pp.pprint(body) - if (response.status < 200) or (response.status > 299): + if response.status == 413: + raise cloudlb.errors.ResponseError(response.status, + "Account is currently above limit, please wait until" + + retry + ".") + elif (response.status < 200) or (response.status > 299): raise cloudlb.errors.ResponseError(response.status, response.reason) From 3352936e0700cf09f3428563956d40c46392fa92 Mon Sep 17 00:00:00 2001 From: Aaron Levy Date: Thu, 9 Feb 2012 11:41:33 -0800 Subject: [PATCH 23/55] Inherit a base exception class to make catching cloudlb specific exceptions easier. --- cloudlb/errors.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cloudlb/errors.py b/cloudlb/errors.py index 37890ba..00ac86a 100644 --- a/cloudlb/errors.py +++ b/cloudlb/errors.py @@ -2,7 +2,9 @@ __author__ = "Chmouel Boudjnah " -class ResponseError(Exception): +class CloudlbException(Exception): pass + +class ResponseError(CloudlbException): """ Raised when the remote service returns an error. """ @@ -18,28 +20,28 @@ def __repr__(self): return '%d: %s' % (self.status, self.reason) -class InvalidRegion(Exception): +class InvalidRegion(CloudlbException): """ Raised when the region specified is invalid """ pass -class InvalidProtocol(Exception): +class InvalidProtocol(CloudlbException): """ Raised when the protocol specified is invalid """ pass -class AuthenticationFailed(Exception): +class AuthenticationFailed(CloudlbException): """ Raised on a failure to authenticate. """ pass -class InvalidLoadBalancerName(Exception): +class InvalidLoadBalancerName(CloudlbException): def __init__(self, reason): self.reason = reason Exception.__init__(self) From 9f6fb1ba33ba54ccb917a316bb6d0f81e418cec4 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Thu, 15 Mar 2012 16:09:16 -0500 Subject: [PATCH 24/55] Started SSL Termination Update to loadbalancers.py to tie in SSL Termination Created ssltermination and wrote initial code, not complete --- cloudlb/ssltermination.py | 59 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 cloudlb/ssltermination.py diff --git a/cloudlb/ssltermination.py b/cloudlb/ssltermination.py new file mode 100644 index 0000000..65fdc16 --- /dev/null +++ b/cloudlb/ssltermination.py @@ -0,0 +1,59 @@ +# -*- encoding: utf-8 -*- +__author__ = "Jason Straw " + +class SSLTermination(object): + def __repr__(self): + return "" % self.port + + def __init__(self, client, lbId=None): + self.lbId = lbId + if self.lbId: + self.lbId = int(self.lbId) + self.path = "/loadbalancers/%s/ssltermination" % self.lbId + + self.client = client + + def get(self): + ret = self.client.get("%s.json" % self.path) + sslt = ret[1] + self.port = sslt['securePort'] + self.enabled = sslt['enabled'] + self.secureonly = sslt['secureTrafficOnly'] + self.certificate = sslt._json_to_pem(sslt['certificate']) + self.privatekey = sslt._json_to_pem(sslt['privatekey']) + if 'intermediateCertificate' in sslt.keys(): + self.intermediate = sslt_json_to_pem(sslt['intermediateCertificate']) + else: + self.intermediate = None + return ret[1] + + def update(self, **kwargs): + for key, value in kwargs: + + + + def add(self, port, privatekey, certificate, intermediate=None, enabled=True, secureonly=True): + self.port = port + self.enabled = enabled + self.secureonly = secureonly + self.privatekey = privatekey + self.certificate = certificate + self.intermediate = intermediate + body = {'securePort': self.port, 'enabled': self.enabled, 'secureTrafficOnly': self.secureonly} + body['privatekey'] = self._pem_to_json(self.privatekey) + body['certificate'] = self._pem_to_json(self.certificate) + if self.intermediate != None: + body['intermediateCertificate'] = self._pem_to_json(self.intermediate) + self._put(self, body) + + def _put(self, body): + self.client.put(self.path, body=body) + + def _pem_to_json(self, pem): + return pem.replace('\n', '\\n') + + def _json_to_pem(self, string): + return string.replace('\\n', '\n') + + def delete(self): + self.client.delete(self.path) From f59aced3c6d7c28b579cb84f00e5573f2229b1de Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Fri, 16 Mar 2012 00:13:59 -0500 Subject: [PATCH 25/55] Continue writing SSL Termination --- cloudlb/loadbalancers.py | 5 +++++ cloudlb/ssltermination.py | 31 +++++++++++++++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index dc60115..92de039 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -13,6 +13,7 @@ from cloudlb.connectionlogging import ConnectionLogging from cloudlb.connectionthrottle import ConnectionThrottleManager from cloudlb.errorpage import ErrorPage +from cloudlb.ssltermination import SSLTermination class LoadBalancer(base.Resource): accessList = None @@ -94,6 +95,10 @@ def connection_throttling(self): ) return ctm + def ssl_termination(self): + sslt = SSLTermination(self.manager.api.client, base.getid(self)) + return sslt + class LoadBalancerManager(base.ManagerWithFind): resource_class = LoadBalancer diff --git a/cloudlb/ssltermination.py b/cloudlb/ssltermination.py index 65fdc16..4ee5093 100644 --- a/cloudlb/ssltermination.py +++ b/cloudlb/ssltermination.py @@ -2,6 +2,14 @@ __author__ = "Jason Straw " class SSLTermination(object): + self.kwargs = {'port': 'securePort', + 'enabled': 'enabled', + 'secureonly': 'secureTrafficOnly', + 'certificate': 'certificate', + 'intermediate': 'intermediateCertificate', + 'privatekey': 'privatekey' + } + def __repr__(self): return "" % self.port @@ -16,20 +24,21 @@ def __init__(self, client, lbId=None): def get(self): ret = self.client.get("%s.json" % self.path) sslt = ret[1] - self.port = sslt['securePort'] - self.enabled = sslt['enabled'] - self.secureonly = sslt['secureTrafficOnly'] - self.certificate = sslt._json_to_pem(sslt['certificate']) - self.privatekey = sslt._json_to_pem(sslt['privatekey']) + for (key, value) in sslt.iteritems(): + key = [k for k, v in self.kwargs.iteritems() if v == value][0] + setattr(self, key, value) if 'intermediateCertificate' in sslt.keys(): self.intermediate = sslt_json_to_pem(sslt['intermediateCertificate']) else: self.intermediate = None - return ret[1] + return self def update(self, **kwargs): - for key, value in kwargs: - + body = {} + for (key, value) in kwargs.iteritems(): + body[self.kwargs[key]] = value + setattr(self, key, value) + self._put(body) def add(self, port, privatekey, certificate, intermediate=None, enabled=True, secureonly=True): @@ -49,11 +58,5 @@ def add(self, port, privatekey, certificate, intermediate=None, enabled=True, se def _put(self, body): self.client.put(self.path, body=body) - def _pem_to_json(self, pem): - return pem.replace('\n', '\\n') - - def _json_to_pem(self, string): - return string.replace('\\n', '\n') - def delete(self): self.client.delete(self.path) From 8c057a217acbaa13bdaf380bc582cf126c6940b2 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Sun, 18 Mar 2012 21:15:40 -0500 Subject: [PATCH 26/55] Added NotFound error and fixed up SSL Termination NotFound error is called on a 404 error and is a subclass of ResponseError. SSLTermination is now working and somewhat tested. --- cloudlb/client.py | 2 ++ cloudlb/errors.py | 6 +++++ cloudlb/ssltermination.py | 48 ++++++++++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index b73702d..8f10d0b 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -126,6 +126,8 @@ def _cloudlb_request(self, url, method, **kwargs): raise cloudlb.errors.ResponseError(response.status, "Account is currently above limit, please wait until" + retry + ".") + elif response.status == 404: + raise cloudlb.errors.NotFound(response.status, body['message']) elif (response.status < 200) or (response.status > 299): raise cloudlb.errors.ResponseError(response.status, response.reason) diff --git a/cloudlb/errors.py b/cloudlb/errors.py index 00ac86a..f0f68d5 100644 --- a/cloudlb/errors.py +++ b/cloudlb/errors.py @@ -41,6 +41,12 @@ class AuthenticationFailed(CloudlbException): pass +class NotFound(ResponseError): + """ + Raised when there the object wasn't found. + """ + pass + class InvalidLoadBalancerName(CloudlbException): def __init__(self, reason): self.reason = reason diff --git a/cloudlb/ssltermination.py b/cloudlb/ssltermination.py index 4ee5093..cf60cc6 100644 --- a/cloudlb/ssltermination.py +++ b/cloudlb/ssltermination.py @@ -1,8 +1,10 @@ # -*- encoding: utf-8 -*- __author__ = "Jason Straw " +import cloudlb.errors + class SSLTermination(object): - self.kwargs = {'port': 'securePort', + kwargs = {'port': 'securePort', 'enabled': 'enabled', 'secureonly': 'secureTrafficOnly', 'certificate': 'certificate', @@ -11,7 +13,10 @@ class SSLTermination(object): } def __repr__(self): - return "" % self.port + try: + return "" % self.port + except AttributeError: + return "" def __init__(self, client, lbId=None): self.lbId = lbId @@ -22,7 +27,14 @@ def __init__(self, client, lbId=None): self.client = client def get(self): - ret = self.client.get("%s.json" % self.path) + """Get dictionary of current LB settings. + + Returns None if SSL Termination is not configured. + """ + try: + ret = self.client.get("%s.json" % self.path) + except cloudlb.errors.NotFound: + return None sslt = ret[1] for (key, value) in sslt.iteritems(): key = [k for k, v in self.kwargs.iteritems() if v == value][0] @@ -34,14 +46,28 @@ def get(self): return self def update(self, **kwargs): + """Update SSL Termination settings: + + Takes keyword args of items to update. + + If you're updating the cert/key/intermediate certificate, + you must provide all 3 keywords. + """ body = {} - for (key, value) in kwargs.iteritems(): - body[self.kwargs[key]] = value - setattr(self, key, value) + if self.intermediate != None: + s = set(['privatekey','certificate','intermediate']) + else: + s = set(['privatekey','certificate']) + if len(s.difference_update(set(kwargs))) == 0: + for (key, value) in kwargs.iteritems(): + body[self.kwargs[key]] = value + setattr(self, key, value) + else: + raise self._put(body) - def add(self, port, privatekey, certificate, intermediate=None, enabled=True, secureonly=True): + def add(self, port, privatekey, certificate, intermediate=None, enabled=True, secureonly=False): self.port = port self.enabled = enabled self.secureonly = secureonly @@ -49,11 +75,11 @@ def add(self, port, privatekey, certificate, intermediate=None, enabled=True, se self.certificate = certificate self.intermediate = intermediate body = {'securePort': self.port, 'enabled': self.enabled, 'secureTrafficOnly': self.secureonly} - body['privatekey'] = self._pem_to_json(self.privatekey) - body['certificate'] = self._pem_to_json(self.certificate) + body['privatekey'] = self.privatekey + body['certificate'] = self.certificate if self.intermediate != None: - body['intermediateCertificate'] = self._pem_to_json(self.intermediate) - self._put(self, body) + body['intermediateCertificate'] = self.intermediate + self._put(body) def _put(self, body): self.client.put(self.path, body=body) From a188debc2b369cba1d023c1067eaeb014fb8098d Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Wed, 28 Mar 2012 00:00:02 -0500 Subject: [PATCH 27/55] Fix 413 code to make it not crash if you get a second count. --- cloudlb/client.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 8f10d0b..e28f0a0 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -8,6 +8,7 @@ import time import datetime +import cloudlb.base import cloudlb.consts import cloudlb.errors @@ -95,6 +96,8 @@ def _cloudlb_request(self, url, method, **kwargs): pp.pprint(json.loads(kwargs['body'])) response, body = self.request(fullurl, method, **kwargs) + if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + sys.stderr.write("RETURNED HEADERS: %s\n" % (str(response))) # If we hit a 413 (Request Limit) response code, # check to see how long we have to wait. # If you have to wait more then 10 seconds, @@ -102,15 +105,30 @@ def _cloudlb_request(self, url, method, **kwargs): if response.status == 413: now = datetime.datetime.strptime(response['date'], '%a, %d %b %Y %H:%M:%S %Z') - retry = datetime.datetime.strptime(response['retry-after'], - '%a, %d %b %Y %H:%M:%S %Z') - if (retry - now) > datetime.timedelta(seconds=10): - raise cloudlb.errors.ResponseError(response.status, - "Account is currently above limit, please wait " - + (retry - now) + ".") + # Retry-After header now doesn't always return a timestamp, + # try parsing the timestamp, if that fails wait 5 seconds + # and try again. If it succeeds figure out how long to wait + try: + retry = datetime.datetime.strptime(response['retry-after'], + '%a, %d %b %Y %H:%M:%S %Z') + except ValueError: + if response['retry-after'] > '30': + raise cloudlb.errors.ResponseError(response.status, + "Account is currently above limit, please wait %s seconds." % + (response['retry-after'])) + else: + time.sleep(10) + response, body = self.request(fullurl, method, **kwargs) + except: + raise else: - time.sleep((retry - now).seconds) - response, body = self.request(fullurl, method, **kwargs) + if (retry - now) > datetime.timedelta(seconds=10): + raise cloudlb.errors.ResponseError(response.status, + "Account is currently above limit, please wait %s seconds." % + (retry - now)) + else: + time.sleep((retry - now).seconds) + response, body = self.request(fullurl, method, **kwargs) if body: try: From dee0182798fa533ba72a64e5d592a4db6d26ea00 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Wed, 28 Mar 2012 21:04:53 -0500 Subject: [PATCH 28/55] Fixed sleep timer to match comment --- cloudlb/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index e28f0a0..fd7ebdc 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -117,7 +117,7 @@ def _cloudlb_request(self, url, method, **kwargs): "Account is currently above limit, please wait %s seconds." % (response['retry-after'])) else: - time.sleep(10) + time.sleep(5) response, body = self.request(fullurl, method, **kwargs) except: raise From 4f4d7b010e817152f1abce0df63fe1bde6ff2bf9 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Sun, 1 Apr 2012 22:36:34 -0500 Subject: [PATCH 29/55] Fix Bugs in SSL Termination Code --- cloudlb/ssltermination.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/cloudlb/ssltermination.py b/cloudlb/ssltermination.py index cf60cc6..0d2c37a 100644 --- a/cloudlb/ssltermination.py +++ b/cloudlb/ssltermination.py @@ -25,6 +25,7 @@ def __init__(self, client, lbId=None): self.path = "/loadbalancers/%s/ssltermination" % self.lbId self.client = client + self.get() def get(self): """Get dictionary of current LB settings. @@ -35,12 +36,16 @@ def get(self): ret = self.client.get("%s.json" % self.path) except cloudlb.errors.NotFound: return None - sslt = ret[1] - for (key, value) in sslt.iteritems(): - key = [k for k, v in self.kwargs.iteritems() if v == value][0] - setattr(self, key, value) + sslt = ret[1]['sslTermination'] + for (skey, value) in sslt.iteritems(): + key = [k for (k, v) in self.kwargs.iteritems() if v == skey] + try: + setattr(self, key[0], value) + except IndexError: + print skey, repr(key) + raise if 'intermediateCertificate' in sslt.keys(): - self.intermediate = sslt_json_to_pem(sslt['intermediateCertificate']) + self.intermediate = sslt['intermediateCertificate'] else: self.intermediate = None return self @@ -54,16 +59,9 @@ def update(self, **kwargs): you must provide all 3 keywords. """ body = {} - if self.intermediate != None: - s = set(['privatekey','certificate','intermediate']) - else: - s = set(['privatekey','certificate']) - if len(s.difference_update(set(kwargs))) == 0: - for (key, value) in kwargs.iteritems(): - body[self.kwargs[key]] = value - setattr(self, key, value) - else: - raise + for (key, value) in kwargs.iteritems(): + body[self.kwargs[key]] = value + setattr(self, key, value) self._put(body) From 02e4a39a1f4c9e7a989ac2baa963ca3d063ef391 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Wed, 18 Apr 2012 21:37:36 -0500 Subject: [PATCH 30/55] Updated Error Handling to make it return the message from the API. --- cloudlb/client.py | 23 ++++++++++++++++++++--- cloudlb/errors.py | 13 +++++++++++-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index fd7ebdc..61e6f8a 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -38,7 +38,7 @@ def __init__(self, elif region.lower() in cloudlb.consts.REGION.keys(): self.region = cloudlb.consts.REGION[region] else: - raise cloudlb.errors.InvalidRegion() + raise cloudlb.errors.InvalidRegion(region) self.auth_token = None self.account_number = None @@ -48,20 +48,34 @@ def authenticate(self): headers = {'Content-Type': 'application/json'} body = '{"credentials": {"username": "%s", "key": "%s"}}' \ % (self.username, self.api_key) + + #DEBUGGING: + if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + pp = pprint.PrettyPrinter(stream=sys.stderr, indent=2) + sys.stderr.write("URL: %s\n" % (self._auth_url)) + response, body = self.request(self._auth_url, 'POST', body=body, headers=headers) - auth_data = json.loads(body)['auth'] + if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + sys.stderr.write("RETURNED HEADERS: %s\n" % (str(response))) + sys.stderr.write("BODY:") + pp.pprint(body) + + data = json.loads(body) # A status code of 401 indicates that the supplied credentials # were not accepted by the authentication service. if response.status == 401: - raise cloudlb.errors.AuthenticationFailed() + reason = data['unauthorized']['message'] + raise cloudlb.errors.AuthenticationFailed(response.status, reason) if response.status != 200: raise cloudlb.errors.ResponseError(response.status, response.reason) + auth_data = data['auth'] + self.account_number = int(os.path.basename( auth_data['serviceCatalog']['cloudServers'][0]['publicURL'])) self.auth_token = auth_data['token']['id'] @@ -103,6 +117,9 @@ def _cloudlb_request(self, url, method, **kwargs): # If you have to wait more then 10 seconds, # raise ResponseError with a more sane message then CLB provides if response.status == 413: + if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + sys.stderr.write("(413) BODY:") + pp.pprint(body) now = datetime.datetime.strptime(response['date'], '%a, %d %b %Y %H:%M:%S %Z') # Retry-After header now doesn't always return a timestamp, diff --git a/cloudlb/errors.py b/cloudlb/errors.py index f0f68d5..6b7169d 100644 --- a/cloudlb/errors.py +++ b/cloudlb/errors.py @@ -1,6 +1,7 @@ # -*- encoding: utf-8 -*- __author__ = "Chmouel Boudjnah " +import cloudlb.consts class CloudlbException(Exception): pass @@ -24,8 +25,16 @@ class InvalidRegion(CloudlbException): """ Raised when the region specified is invalid """ - pass + regions = cloudlb.consts.REGION.values() + cloudlb.consts.REGION.keys() + def __init__(self, region): + self.region = region + Exception.__init__(self) + def __str__(self): + return 'Region %s not in active region list: %s' % (self.region, ', '.join(self.regions)) + + def __repr__(self): + return 'Region %s not in active region list: %s' % (self.region, ', '.join(self.regions)) class InvalidProtocol(CloudlbException): """ @@ -34,7 +43,7 @@ class InvalidProtocol(CloudlbException): pass -class AuthenticationFailed(CloudlbException): +class AuthenticationFailed(ResponseError): """ Raised on a failure to authenticate. """ From 092c8c528b7e79a1d316e4c46461e1b882a7d76b Mon Sep 17 00:00:00 2001 From: Chris Hannam Date: Thu, 26 Apr 2012 15:04:50 +0100 Subject: [PATCH 31/55] Adds algorithm to the create call to allow it to be specified, defaults to RANDOM --- cloudlb/loadbalancers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 92de039..428e9be 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -136,7 +136,7 @@ def search(self, ip): def create(self, name, port, - protocol, nodes, virtualIps): + protocol, nodes, virtualIps, algorithm=None): """ Create a new loadbalancer. @@ -153,12 +153,16 @@ def create(self, name, port, if len(name) > 128: raise InvalidLoadBalancerName("LB name is too long.") + if not algorithm: + algorithm = 'RANDOM' + body = {"loadBalancer": { "name": name, "port": base.getid(port), "protocol": protocol, "nodes": nodeDico, "virtualIps": vipDico, + "algorithm": algorithm, }} return self._create("/loadbalancers", body, "loadBalancer") From 3a74f70b6179023e42202f9cc6a4c608ff1163f1 Mon Sep 17 00:00:00 2001 From: Chris Hannam Date: Thu, 10 May 2012 14:53:01 +0100 Subject: [PATCH 32/55] changed default value to random --- cloudlb/loadbalancers.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 428e9be..bdf94ad 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -136,7 +136,7 @@ def search(self, ip): def create(self, name, port, - protocol, nodes, virtualIps, algorithm=None): + protocol, nodes, virtualIps, algorithm='RANDOM'): """ Create a new loadbalancer. @@ -153,9 +153,6 @@ def create(self, name, port, if len(name) > 128: raise InvalidLoadBalancerName("LB name is too long.") - if not algorithm: - algorithm = 'RANDOM' - body = {"loadBalancer": { "name": name, "port": base.getid(port), From db63316e0961ecae531ee6a8e0dd428117acf8e8 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Sun, 13 May 2012 18:49:21 -0500 Subject: [PATCH 33/55] Updated up VERSION in prep for a release --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 05fba0d..6d358c2 100755 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ def read(fname): try: from cloudlb.consts import VERSION except ImportError: - VERSION="0.0.0" + VERSION="0.4.0" for line in read('cloudlb/consts.py').split('\n'): if line.startswith('VERSION'): VERSION = line.split('=')[1].replace('"', '').replace("'", '').strip() From 588a046e5a5ec96321744934a992b2dd038fa9a4 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Tue, 22 May 2012 15:05:02 -0500 Subject: [PATCH 34/55] Added Error Handlers for various status codes --- cloudlb/client.py | 23 +++++++++++++---------- cloudlb/errors.py | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index 61e6f8a..ceaaf56 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -130,9 +130,7 @@ def _cloudlb_request(self, url, method, **kwargs): '%a, %d %b %Y %H:%M:%S %Z') except ValueError: if response['retry-after'] > '30': - raise cloudlb.errors.ResponseError(response.status, - "Account is currently above limit, please wait %s seconds." % - (response['retry-after'])) + raise cloudlb.errors.RateLimit(response['retry-after']) else: time.sleep(5) response, body = self.request(fullurl, method, **kwargs) @@ -140,9 +138,7 @@ def _cloudlb_request(self, url, method, **kwargs): raise else: if (retry - now) > datetime.timedelta(seconds=10): - raise cloudlb.errors.ResponseError(response.status, - "Account is currently above limit, please wait %s seconds." % - (retry - now)) + raise cloudlb.errors.RateLimit((retry - now)) else: time.sleep((retry - now).seconds) response, body = self.request(fullurl, method, **kwargs) @@ -158,14 +154,21 @@ def _cloudlb_request(self, url, method, **kwargs): pp.pprint(body) if response.status == 413: - raise cloudlb.errors.ResponseError(response.status, - "Account is currently above limit, please wait until" - + retry + ".") + raise cloudlb.errors.RateLimit(retry) elif response.status == 404: raise cloudlb.errors.NotFound(response.status, body['message']) + elif response.status == 400: + raise cloudlb.errors.BadRequest(response.status, body['message']) + elif response.status == 422: + if 'unprocessable' in body['message']: + raise cloudlb.errors.UnprocessableEntity(response.status, + body['message']) + else: + raise cloudlb.errors.ImmutableEntity(response.status, + body['message']) elif (response.status < 200) or (response.status > 299): raise cloudlb.errors.ResponseError(response.status, - response.reason) + body['message']) return response, body diff --git a/cloudlb/errors.py b/cloudlb/errors.py index 6b7169d..3ea2d34 100644 --- a/cloudlb/errors.py +++ b/cloudlb/errors.py @@ -20,6 +20,30 @@ def __str__(self): def __repr__(self): return '%d: %s' % (self.status, self.reason) +class RateLimit(ResponseError): + """ + Raised when too many requests have been made + of the remote service in a given time period. + """ + self.status = 413 + + def __init__(self, wait): + self.wait = wait + self.reason = "Account is currently above limit, please wait %s seconds." % (wait) + Exception.__init__(self) + +class BadRequest(ResponseError): + """ + Raised when the request doesn't match what was anticipated. + """ + pass + +# Immutable and Unprocessable Entity are both 422 errors, but have slightly different meanings +class ImmuntableEntity(ResponseError): + pass + +class UnprocessableEntity(ResponseError): + pass class InvalidRegion(CloudlbException): """ From 3d94160871e85cf2efd29aa57c0e244b84dbd402 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Wed, 30 May 2012 00:03:35 -0500 Subject: [PATCH 35/55] Adding and Deleting nodes now updates the NodeDict --- cloudlb/loadbalancers.py | 4 +++- cloudlb/node.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index bdf94ad..54b59f6 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -50,7 +50,9 @@ def _add_details(self, info): def add_nodes(self, nodes): resp, body = self.manager.add_nodes(self.id, nodes) - return [Node(parent=self, **x) for x in body['nodes']] + n = [Node(parent=self, **x) for x in body['nodes']] + self.nodes.add(n) + return n def update(self): self.manager.update(self, self._info, self.__dict__) diff --git a/cloudlb/node.py b/cloudlb/node.py index a5b32b6..ca794c5 100644 --- a/cloudlb/node.py +++ b/cloudlb/node.py @@ -29,6 +29,24 @@ def filter(self, ret.append(d) return ret + def add(self, nodes): + """Add a list of Nodes to the NodeDict. + + This DOES NOT actually add nodes to the LB, + it should be called from the LB's add_nodes method""" + for node in nodes: + self.dico.append(node) + + def delete(self, nid): + """Delete a Node from the NodeDict. + + This DOES NOT actually remove nodes from the LB, + it should be called from the node.delete() method""" + for x in range(len(self.dico)): + if self.dico[x].id == nid: + del self.dico[x] + + class Node(SubResource): def __repr__(self): @@ -61,6 +79,7 @@ def delete(self): self._parent.manager.delete_node(self._parent.id, self.id, ) + self._parent.nodes.delete(self.id) def update(self): ret = {} From cc1dfc46de81139f690b4ce0f3eb565d5e1e7c01 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Wed, 30 May 2012 00:43:43 -0500 Subject: [PATCH 36/55] Make client call new Errors properly Fix syntax error in errors.py --- cloudlb/client.py | 23 ++++++++++++++--------- cloudlb/errors.py | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index ceaaf56..84ad4f0 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -153,24 +153,29 @@ def _cloudlb_request(self, url, method, **kwargs): sys.stderr.write("BODY:") pp.pprint(body) + if (response.status >= 200) and (response.status < 300): + return response, body + + try: + message = ', '.join(body['messages']) + except KeyError: + message = body['message'] if response.status == 413: raise cloudlb.errors.RateLimit(retry) elif response.status == 404: - raise cloudlb.errors.NotFound(response.status, body['message']) + raise cloudlb.errors.NotFound(response.status, message) elif response.status == 400: - raise cloudlb.errors.BadRequest(response.status, body['message']) + raise cloudlb.errors.BadRequest(response.status, message) elif response.status == 422: - if 'unprocessable' in body['message']: + if 'unprocessable' in message: raise cloudlb.errors.UnprocessableEntity(response.status, - body['message']) + message) else: raise cloudlb.errors.ImmutableEntity(response.status, - body['message']) - elif (response.status < 200) or (response.status > 299): + message) + else: raise cloudlb.errors.ResponseError(response.status, - body['message']) - - return response, body + message) def put(self, url, **kwargs): return self._cloudlb_request(url, 'PUT', **kwargs) diff --git a/cloudlb/errors.py b/cloudlb/errors.py index 3ea2d34..379746b 100644 --- a/cloudlb/errors.py +++ b/cloudlb/errors.py @@ -25,7 +25,7 @@ class RateLimit(ResponseError): Raised when too many requests have been made of the remote service in a given time period. """ - self.status = 413 + status = 413 def __init__(self, wait): self.wait = wait From cf160bf30453df77bf970383b2ab548a61226d93 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Sat, 2 Jun 2012 19:47:21 -0500 Subject: [PATCH 37/55] Fix Version Number --- cloudlb/consts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/consts.py b/cloudlb/consts.py index 4b649a1..cd0b616 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -1,6 +1,6 @@ # -*- encoding: utf-8 -*- __author__ = "Chmouel Boudjnah " -VERSION = "0.4" +VERSION = "0.5.1" USER_AGENT = 'python-cloudb/%s' % VERSION # Default AUTH SERVER From a76a48963a75297f01c1e6f52c9ec720fb3366a2 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Sat, 7 Jul 2012 21:27:54 -0500 Subject: [PATCH 38/55] Fixing spelling of Immutable in class name --- cloudlb/errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/errors.py b/cloudlb/errors.py index 379746b..a82ff58 100644 --- a/cloudlb/errors.py +++ b/cloudlb/errors.py @@ -39,7 +39,7 @@ class BadRequest(ResponseError): pass # Immutable and Unprocessable Entity are both 422 errors, but have slightly different meanings -class ImmuntableEntity(ResponseError): +class ImmutableEntity(ResponseError): pass class UnprocessableEntity(ResponseError): From 3c976138fd103a16dee8a13a26712c5d260fa091 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Tue, 10 Jul 2012 19:53:49 +0300 Subject: [PATCH 39/55] s/persistense/persistence/ Reported by James Mackinnon. --- README.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 14541df..7916f77 100644 --- a/README.rst +++ b/README.rst @@ -289,7 +289,7 @@ Delete Health Monitor rule:: hm_monitor = mylb.healthmonitor() hm_monitor.delete() -Add http cookie session persistense:: +Add http cookie session persistence:: #!/usr/bin/python import cloudlb @@ -298,9 +298,9 @@ Add http cookie session persistense:: lbs = clb.loadbalancers.list() mylb = lbs[0] #first lb - ss = cloudlb.sessionpersistense.SessionPersistense(persistenceType="HTTP_COOKIE") + ss = cloudlb.sessionpersistence.SessionPersistence(persistenceType="HTTP_COOKIE") - ssp = mylb.session_persistense() + ssp = mylb.session_persistence() ssp.add(ss) Get session persistence:: @@ -312,10 +312,10 @@ Get session persistence:: lbs = clb.loadbalancers.list() mylb = lbs[0] #first lb - ssp = mylb.session_persistense() + ssp = mylb.session_persistence() print ssp.get() -Delete session persistense configuration:: +Delete session persistence configuration:: #!/usr/bin/python import cloudlb @@ -324,7 +324,7 @@ Delete session persistense configuration:: lbs = clb.loadbalancers.list() mylb = lbs[0] #first lb - ssp = mylb.session_persistense() + ssp = mylb.session_persistence() ssp.delete() Enable/Disable Connection Logging:: @@ -404,3 +404,4 @@ Author Chmouel Boudjnah + From 4aa0bf5111e447a0f2b9d2da424b0b5cfc047329 Mon Sep 17 00:00:00 2001 From: Jessica Lucci Date: Thu, 20 Sep 2012 12:51:51 -0500 Subject: [PATCH 40/55] LoadBalancer client now supports metadata field --- cloudlb/.base.py.swp | Bin 0 -> 16384 bytes cloudlb/.client.py.swp | Bin 0 -> 16384 bytes cloudlb/.loadbalancers.py.swp | Bin 0 -> 20480 bytes cloudlb/__init__.pyc | Bin 0 -> 2398 bytes cloudlb/accesslist.pyc | Bin 0 -> 2411 bytes cloudlb/base.pyc | Bin 0 -> 8687 bytes cloudlb/cli_help.pyc | Bin 0 -> 6005 bytes cloudlb/client.py | 14 +++++++------- cloudlb/client.pyc | Bin 0 -> 5751 bytes cloudlb/connectionlogging.pyc | Bin 0 -> 1443 bytes cloudlb/connectionthrottle.pyc | Bin 0 -> 1284 bytes cloudlb/consts.pyc | Bin 0 -> 1023 bytes cloudlb/errorpage.pyc | Bin 0 -> 1366 bytes cloudlb/errors.pyc | Bin 0 -> 4330 bytes cloudlb/healthmonitor.pyc | Bin 0 -> 1750 bytes cloudlb/loadbalancers.py | 7 ++++--- cloudlb/loadbalancers.pyc | Bin 0 -> 8854 bytes cloudlb/node.pyc | Bin 0 -> 3415 bytes cloudlb/sessionpersistence.pyc | Bin 0 -> 1339 bytes cloudlb/ssltermination.pyc | Bin 0 -> 3171 bytes cloudlb/stats.pyc | Bin 0 -> 801 bytes cloudlb/usage.pyc | Bin 0 -> 959 bytes cloudlb/virtualip.pyc | Bin 0 -> 1231 bytes 23 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 cloudlb/.base.py.swp create mode 100644 cloudlb/.client.py.swp create mode 100644 cloudlb/.loadbalancers.py.swp create mode 100644 cloudlb/__init__.pyc create mode 100644 cloudlb/accesslist.pyc create mode 100644 cloudlb/base.pyc create mode 100644 cloudlb/cli_help.pyc create mode 100644 cloudlb/client.pyc create mode 100644 cloudlb/connectionlogging.pyc create mode 100644 cloudlb/connectionthrottle.pyc create mode 100644 cloudlb/consts.pyc create mode 100644 cloudlb/errorpage.pyc create mode 100644 cloudlb/errors.pyc create mode 100644 cloudlb/healthmonitor.pyc create mode 100644 cloudlb/loadbalancers.pyc create mode 100644 cloudlb/node.pyc create mode 100644 cloudlb/sessionpersistence.pyc create mode 100644 cloudlb/ssltermination.pyc create mode 100644 cloudlb/stats.pyc create mode 100644 cloudlb/usage.pyc create mode 100644 cloudlb/virtualip.pyc diff --git a/cloudlb/.base.py.swp b/cloudlb/.base.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..8031dfddb40f6ba633e39f6145f08e51b5d46b7b GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/cloudlb/.client.py.swp b/cloudlb/.client.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..0b743d3a77236eb4b8c5afaa597b34ce0396afd1 GIT binary patch literal 16384 zcmeHOU2Ggz6&{-YK%h`40z_2lX07e)M(g!o0>z4>uH%hk>Lkv_8V{M^|zN6*fkVDB$aD7bD>l<%Lod*PM)zP9Iv>lI~{yY9h> zu{)?~r|ZP%_@S}t2P?DZcIu@lACm+}X1KfNS@y_+W3BR*=Z@H$UdJ+rTZZMgjpj&v z*SYDH?aiGDXRVn8G70QL0yirY<71=LaVWQ+-TIFDF2-bCG6`f7$RvA7c>2wX@*CiLz?Xn^zz5C&IpEiO73J%|Rp1Js1GfV&yh%}h4?F^N zfED00GEMj;3nYNn?Miv2+#ly1Ao6!QN9B_4qO4g0C3YF6`sKU{+I5#Z!<7|~7nH-F z!<1W=>3VLtex_P$RA#Fu7o!OR8fBM5)ytZ1cm-9GE3vJM#U=Ga!xi7_3@=)1+!REG zEHyl9c=RkHHN+e~OwTbpt%ftrY%|Z?yVDZ$K%=T5HyM5~soE5wS1mP`vPOE1;R@ytP1p3hP42`DP=`KU*Q&E~*h$#5v|AIb z6-x?rrz`O^xhsObGZJncMRb+DW4)u7_|n!qZAlgCA?w!L>iK90OLl>2uInv+6#Wfr zh58DX&){*eGe+^q_M6xW;95POa4ji|$MkS61^5M9^E&0G=5kZ(@aNHVNtwK=nv#U4e35MIOu z5zP~nT%Q~zD7WAPh@@t?u{KG^Sd?(ghNZRL0(s72+<}yA+vOlcg^fwY$MH#qyy;Uj z=O%N#3LorMt1i}SC#y5;c(pQ9t({3kNkqO#C&h$8L!!Hjb&(E|j1GRLl}^z=B^J8x zsqh{%FHH?z7abv~aQh2K8F+|>*fSy~stc#iEUKkm=?$*EHz^PlBO;0Q634GIKiIX% zq;yi#gRoJ$M1&ZJ+y(*)Id9F@8*3akBWZ+^QnzvmlgmxAt(+W*FGw_UC6>d$@XN)E zD!V755h?-#-|CJ1lWZ{ZUlhYASdc2BSVP<;BSNUU{(J^=oU}|HO&u(%CupR1!CXN! zm(39ghAY+o%$e(&p|@)yse+LcFR|db;qur!5RnASm_$0vFf$3F)lxtuc0Ak=u7^mM z4GSKoP^3gCb#NK-cMA{_O(w72NdxkVYw-J^>s7{(_qPDnPaRY2Y^CAE?KF3S0uHKA#2thFbhN;OD@1fi2(z zzz{$+`oq9Oz^8$W0M+KtqZa=K@D%VxzyWH&Y2X&%kEq9A0-gr00-pseU>)0tm)x^B4)7hy{Sagas-Pg>n5oWJ7prQb0uq~)HgTI9948QB3kMZ@T9vemIf9%f zuCbySY|Hho0sYx3Ql=F0s64L$^@Vymb=!Yc>QWDM5A*vtR@1}O5WmYZW-wY2MR}!8 zM~$gd&UL%Kr!@^;MSAaTM#(eIqIzp5qHrxIuA8=Fk^A3aa;DI%@}h*)PmU4?RpD~u zG$hPn!V)qpbf|n9ACEf`%~W|zYsj#I3|;2$QWS%V+;%FeC?(t5PIc1qj^SV|rHC9* z;r0_9+{HvSgtvLUt9#Hcj)!7H6bad&pvES8iH7VTj!}A^R34i49* z46WO2YxHQ6p~m+Lg*6=RQte+*HMgbfYO%!Diy|dk!zXe6+gvT<6uOHXysxYj3X(iy zwZuW6#$;=+%3wbt9?8SF@Z`9Jebsjq*CPcx}*LGtQ zk|VZvSE*Y+-X=Zt2k8bTM+dC|2kZ!)cZm$LOk5&-dK%)7U~6iOj7_pc_jI-dOTGQX zrs^Fl>HNDSduVXA>Fg3CuOdasn<%o^<*DU*6LuQr1XS9Cer$kvCnL_MYsmv? zwxQ#NipIJYwCrjomze~Wy(Xi&7rD^7-sZ9YA0i{!w0zdl*6~&*u!eww7&JC2l^Y9b zh_yPLUbI+f|Ls_rtT#AcKTobvS^1+<>GA<+BwF9iq1aH5KLsxy6u(m{+%#?rxomD+6oS$6nt H3L*GkrcJQp literal 0 HcmV?d00001 diff --git a/cloudlb/.loadbalancers.py.swp b/cloudlb/.loadbalancers.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..a88aee80b709a04f62aef1d05806150dc16f25e0 GIT binary patch literal 20480 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 literal 0 HcmV?d00001 diff --git a/cloudlb/accesslist.pyc b/cloudlb/accesslist.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2879144387f9b97c528e0646c61cab99b255205 GIT binary patch literal 2411 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 literal 0 HcmV?d00001 diff --git a/cloudlb/cli_help.pyc b/cloudlb/cli_help.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e9a24b85525942f030816844baba6bdc9fd4cfe GIT binary patch literal 6005 zcmb_g?Qhyf7FMJS+Q%~)Wj~`mAF0Yf>1f74>yNu;M;Yj*afUkP@v&m4Na-J1vK%w^2(l3k0w3AF zAKZAeOIRUqM)Bgpb}(D?ZRd*2*`mYH$lbtp_u95^&m6o!1TU^V2Ule|5@0oDz+}5F zJe>u$DTWsp`_pUJFj1m(7N4`y#VV~=f zxo_WwbQi$_(FtZUV+K|7S1BgUd@$bVV>BY(2*d0g-hb-X7enIh1$fk7Roi8aS0Q!WxPELR`@ggJCH5Ik3 zbQPlm4$@ULv!}RaXs67%XdWzRt7rBHV5R6YUj#I80>4!`8Vq`?_wdJFtX0qKRoQ1Z z-D~@o!NLO#T9vM*Sc7rLGz_i7Lcm(}!T;v*s&Aec>bP&Vbz_xM#?s*XRMQWS2AVp) z%Od$nV6rP~pX}+}$IZ`G`uNtsHwLI*PjPSqG-{1HO7sSeAv|Nn1j+xKyo1{Qt5hDh zt|*b)Ep|PNgVf`K!Hf(?0HBIGgfb#S-fggL(0s!=i`AsJCH%jQ{{TdaV< z-<|xulUvM{kOSriT@#`-lbfH*CaM5or9e@sV1+XeS1>Neo2e~#kkZ>ZZdIam^C?RNl?qSil(aEaO{`)YO5(N6W70S|ZfpH@ zgd;S!>7>Q&*;58bh)|m@NgrS0Pp!UosQuboM~cvS;NFTm(OK*a0yQJ!jV+8+j*L_m z1ct^a*K6g(5`3{i-+k7n;y%dYX&cc@|8ivd@=t=WhKOc^R46mdjxPo5q9x0}jT*1^ z&qlSq*Wu&)vS2-EFccz9CV!+O0_%Ds+i@Tn#;m)heTp^K8KyVE;tGWupsx}th9x5w zXi-J!cFoh3su>@5n}#+xHTxf8SBaj=)8(rKXVa`Vey-NwU;SkRjJ=0AAXYu0gWK8E z7Cvx$#2~3t3!Hr&f2%Y<6bJau7Vt zql7<5IMXm>Fan|q^b0b_j(6cXyEz|m;DVU*D-OtN@C^PEoFo<5; zp3fVVSm?8xioC|TrshmoCuZHiIoY$8ak_&Qeun0V&xq(a91;;L+^qJqxi}t+lOZrP z(ZyNn!A#@a0#ZRVue;7Aqe%Dpx|N?2qA09*4Efa6obgxffc@LE^v#AA&SP?wFcNoB$FQ= zCMPrAjz*%vNLZ6rB7R<=x~y|$cBW7{o6K)$^j`16`S(nI@A+_+~PAC zUGT-a1pA5(S@0V6<0AD61jTfGGKxrB!W7PNGmCIHGmy!#k>oT8cjfBnHkw2#Kn8@z zi~Dsb7R4LpL5&qq4m%&D8_|m%+a^r8EjJR8=Q~NHgck@X6Dwg46Ik4TqUWKc^2>-! z%85-a5+%mdHu`Ks28NA<^Bl?LeE|r*EgumZ@-G6hkt_uvn2yyTQR6f;BbMUcJfMow z>A*xa?&@&ipsO(2_~N-R8L|sl!B!S-kyVNs%YDF#XmS9HQaQr14Rwky+mY`>mfgKQ zrpn+FQ`2?dx-Z!OzFNlXh3{u!Gz2(x)EWIq{Y=4rZOX-mI|e^a%tHqg>_r>`lnhU-*G>*-zdumW#V`XJ9?86BfvI=(k% oce&O1Ef@V}8n{azzlD}Bk+0!V`nFUneN$?c%BAm0&r1*g1yzV&UH||9 literal 0 HcmV?d00001 diff --git a/cloudlb/client.py b/cloudlb/client.py index e06cbb6..f0c3f1e 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -100,13 +100,13 @@ def _cloudlb_request(self, url, method, **kwargs): fullurl = "%s%s%s" % (self.region_account_url, url, ext) #DEBUGGING: - if 'PYTHON_CLOUDLB_DEBUG' in os.environ: - pp = pprint.PrettyPrinter(stream=sys.stderr, indent=2) - sys.stderr.write("URL: %s\n" % (fullurl)) - sys.stderr.write("ARGS: %s\n" % (str(kwargs))) - sys.stderr.write("METHOD: %s\n" % (str(method))) - if 'body' in kwargs: - pp.pprint(json.loads(kwargs['body'])) + #if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + pp = pprint.PrettyPrinter(stream=sys.stderr, indent=2) + sys.stderr.write("URL: %s\n" % (fullurl)) + sys.stderr.write("ARGS: %s\n" % (str(kwargs))) + sys.stderr.write("METHOD: %s\n" % (str(method))) + if 'body' in kwargs: + pp.pprint(json.loads(kwargs['body'])) response, body = self.request(fullurl, method, **kwargs) if 'PYTHON_CLOUDLB_DEBUG' in os.environ: diff --git a/cloudlb/client.pyc b/cloudlb/client.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64fd0eb9046302215f3f8895f0ea800ce3d88728 GIT binary patch literal 5751 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 R9QcweA=FQN@OHw-{ugZDF-QOa literal 0 HcmV?d00001 diff --git a/cloudlb/connectionlogging.pyc b/cloudlb/connectionlogging.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5750bcc3cdfd32f6f1b26a96759979f796c4231e GIT binary patch literal 1443 zcmb_cU279T6uqU#IYF3YLOC%cD5d~>{d_6s{Z@=v(b8lwweS@YhG z$CVlX;7;H@;TPWmG`K+t1XoLjO(IgcRWgJTQW>_H267s%N!bj>x}@j5HsS+U@f#QG z`#w&|bq=^n}S0QujaX*cotREl{UV|<-y@} zeUYwVmXfZA5y8EHRn%xkJ=(t$p^k$0=a+sR3$m;-mCv#cY_|ar)xou`UM7XYj5K6D z#c&6JN{J6j99%~=6s4db4R!?XsKK-;2RBMx!kPAx zi=_^g1TE%EpOQJHAR#_w!eM1u6*eqdXn&uI`Mt=`UFbL!wWapd|F1QrnCSyRERa>6 z<+Y0yrd#y>p}h1V9gi4>@vohvu4UyY><-Ld3**LM140vD!(h8`<7~wqVhdxFv!UUH zcVj!dI9T0yzz2>Ld#*oq)}Y78k@bbcf7i0H{<&pj4K2HGIq6eGKF4ruy{N7l^teA) z8`k7Aon@Z zbDu=!lk(^sYXRL7-4K192bA?l`7RpnqCLtEXcpb$tgm1utFqdtVt7_FFcWl{q{c0Y_pKcRGT_g_VK>|G119V)h;}#v{tFjEB$3vSJoD4$E=61 z&M+JX1!jOw3=*8culozS4G3K1EMhfM0mFl_OfU@NfhgBR7es@Z135KM5FPz}{y5@q zZNTPgtvb)B;ygl>oG~vkOAAO+EMBKO7Pe(^vc9q`U>w(KUB~eO=7s^0NSWAnIDDTF zxOVtrOgsh}!}Z++Zr~<9gW_$7U@4$wKsSQSd$OpQ;Q4n!+I7K}<1=I~b7OM79Ga?B z!*x<8rLw9vQHVAB&~4D245kSsmw$#HU{{@3^-kl~nD>u7Xb&Ze_nQ}RXXdTpDm5ty0FV>Vm`hsTkw+go^dN?e{77=~*Xicn0Oo@vxe sHg;8^vn@AAdl60+iBS?hNyh6yNKSL-!yWWdQ=u_yYgpV+4E({<-<|;x*8l(j literal 0 HcmV?d00001 diff --git a/cloudlb/consts.pyc b/cloudlb/consts.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ace11bc0fc7a1ac7d6a0078a0af7022b12e248d GIT binary patch literal 1023 zcma)4+fLg+5FO)?kOT;~Qs^}=RJ`C2mGV#_gku)4aAM0Br254&o-|48WTSXP)&J>R zKd(Q~*$qUmJvKfV?P7zf>31>YlcOvr(tYcoD2@mm3NbA{wp!_2 z42^U;GG=M^wV0+^U(HFK)%CWn zb7^`)o|7yBRmu59B?*g4&IgJRbV*Ihht@)Vl8*bLN5L1W@m!In zd?u6yFX}k9C2BMfF#pcBSdWG3|17uHV^%2St&|QD%XM#U);nA!KoOEe9ygyQi6Y!F zKd{}NYDFZLnAfZqiftOdWLIY7gozo2H;LSb`C^^$==Lv2y71XGi6oKlD1VEkkb63v z#Pi+IwOl6xKOzl5Et4*gb=icULv$PH5bdV7m~=aBYSf|f)o5r zKd(Q~_r}KbQYj%jnVs34d2eQx&Y#!2zfULEi8P-MelM`9Lx@yl0%^nfYcG=-&u}&9xJUbjFwdJDuJx+?{x$ooXkFqSv>-g5SIRjWP z8R;8@Lr$a;rec~c=6^CW={ET%uyoYhleDYKw%Bpl!{x+4Jg+N;BtirjhfFf6UO^69 z1m_{P67qsqDlWUJO|)105J?6`+4RH_^$MtuS9g8~jwmYKs*Iv7o@8(_35&6Sr*RhNi7Ts(q{w|s zgAA1Ht@D;4wAac`&871jaI>WH7E4D)%)lhiOgI|K<`fDb;Y;X7&hR469<;ycEEtli zJ`FVe(HNt>tw|fN{j9(n b)|XLC7cTL7Z__0Dk6>7XKPPl0+6(>yLMi6< literal 0 HcmV?d00001 diff --git a/cloudlb/errors.pyc b/cloudlb/errors.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa9595cd98a449e11f14e134b299dbcbcf869f77 GIT binary patch literal 4330 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 GzWWQX25c<= literal 0 HcmV?d00001 diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 54b59f6..1f9d776 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -138,7 +138,7 @@ def search(self, ip): def create(self, name, port, - protocol, nodes, virtualIps, algorithm='RANDOM'): + protocol, nodes, virtualIps, algorithm='RANDOM', metadata=None): """ Create a new loadbalancer. @@ -154,7 +154,7 @@ def create(self, name, port, if len(name) > 128: raise InvalidLoadBalancerName("LB name is too long.") - + body = {"loadBalancer": { "name": name, "port": base.getid(port), @@ -162,7 +162,8 @@ def create(self, name, port, "nodes": nodeDico, "virtualIps": vipDico, "algorithm": algorithm, - }} + "metadata": metadata + }} return self._create("/loadbalancers", body, "loadBalancer") diff --git a/cloudlb/loadbalancers.pyc b/cloudlb/loadbalancers.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5599c16186f9ae76cba472bcd7d9c9c441c9db22 GIT binary patch literal 8854 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 literal 0 HcmV?d00001 diff --git a/cloudlb/node.pyc b/cloudlb/node.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e64e5945a6784e89d34b9cd46b8772f69f60644 GIT binary patch literal 3415 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 literal 0 HcmV?d00001 diff --git a/cloudlb/stats.pyc b/cloudlb/stats.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3fa281b1df277cf120898ebe24e347479f201de9 GIT binary patch literal 801 zcma)2!EO^V5FI-ql!{6Sq@o^>!l7tSi8yhos;cF}Wra2;_F`?kF4>i1SFv+IDyQ~u z_&k1qH{%E{NU$rvogL4-H}fVxPmX`QZ$Dc)JQIAcaMB#m6SY7^PSLHRUehDd1JRdO zQ$L|qHRZ~8fSb)W?wy}s$9+GBZZp5IC3AK7E^ORh<|im!lmpiCn zs)`xw^cuMIvFq2J?}Bx^v^-DC#52pbd5QwR{?uolVhC9hcU|7(84}hHE@T;1E|T-N z4YxE3P~j9vFA!M|xBR-WFYdnOBP5L(!jO$&tI{!m)HA#<)hlh8gU4iPS^h18vegLR z%7&UwvGjNRh?Qr>xH>&W?Ri>^DTYCYVHTN9R{833!x{0RVRcFGT>i(@4HKW>B;J$M znXW5oFWZD}>x{{~i80&Q?>+x=X&r-W*fe4Iqax8?4QfzK+$vHt_57$VRu}eepEq#_ ab|#JM(b+5=|3fX_UzGVS+2h18)4u>6w~Ge= literal 0 HcmV?d00001 diff --git a/cloudlb/usage.pyc b/cloudlb/usage.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed7e8159b4a6cb61ec8596e3b1eb3a1d688808d5 GIT binary patch literal 959 zcmaJ<&2HN;45nn~7Y)#1L%N>UO9r1(?AAljb?q*_1cS3-K!CxJEj4i(E0CPJ z2ibiOum{@%Y@`x2x7ij&ek8?@l%qd`{;xOl4+ZR>822k&?gE7bn4@GMIcNrRRPc*H zbEqPiN5Igr|6=%oP>al2(xMYyqqtdCrcwIr+B9-ii{;s**dbT@eO#F8viytBG+~(F zi9jx#DoE+$qWuP!1N4^w+ZZ++>?@KhfJcB$OuQyFY7y8Ak_QJ54kW#8QJ|fJjKMQl zaWWqnoS*|!DWVM<2G)VZPzFP^=}drC1QLDtwcw7!5VN)&*mOX4;FL55?kCwZ!ny%l zAk!{X51|9(oP~){vu;cotc~w;TAZ|DkOSUh$Gji4SmUo>t5~so+ z>7l3oy#9dp&DwxesS{I5`tV5#?iL^t?qiL6>JsQKWOE*N%Y}UempHCeS;aBSh7*%W zxJu5zXMMslKLJ;cX$-+*vN2TO2~ayuaO%{j>H~okHm{oypK?TXosYw*N7bBF2)0L; zORS=%wi)OFBEJg`1INaX(WeWK4>doWH~Q_s;G7evCuR8vynC;`Ut=eebo`6RQpfVHf6hK5{uzacq~d6UVb6 ztuv^Rb8y`*auq#=@t%j1{yTON{|UGpvjXUezVD0X4S5LLM6$M%0&{8Esh!@NG@2xQ@a$`-?Tqfq6x!7TS9w}4QRia$(hZ1%5?=%(f@^u>Se^0E4RsS#ZSoDto literal 0 HcmV?d00001 From 6cdcf361b9ff80939260eaebc95ef773e77dcbc3 Mon Sep 17 00:00:00 2001 From: Jessica Lucci Date: Thu, 20 Sep 2012 12:52:20 -0500 Subject: [PATCH 41/55] Removing .swp files --- cloudlb/.base.py.swp | Bin 16384 -> 0 bytes cloudlb/.client.py.swp | Bin 16384 -> 0 bytes cloudlb/.loadbalancers.py.swp | Bin 20480 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cloudlb/.base.py.swp delete mode 100644 cloudlb/.client.py.swp delete mode 100644 cloudlb/.loadbalancers.py.swp diff --git a/cloudlb/.base.py.swp b/cloudlb/.base.py.swp deleted file mode 100644 index 8031dfddb40f6ba633e39f6145f08e51b5d46b7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 diff --git a/cloudlb/.client.py.swp b/cloudlb/.client.py.swp deleted file mode 100644 index 0b743d3a77236eb4b8c5afaa597b34ce0396afd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeHOU2Ggz6&{-YK%h`40z_2lX07e)M(g!o0>z4>uH%hk>Lkv_8V{M^|zN6*fkVDB$aD7bD>l<%Lod*PM)zP9Iv>lI~{yY9h> zu{)?~r|ZP%_@S}t2P?DZcIu@lACm+}X1KfNS@y_+W3BR*=Z@H$UdJ+rTZZMgjpj&v z*SYDH?aiGDXRVn8G70QL0yirY<71=LaVWQ+-TIFDF2-bCG6`f7$RvA7c>2wX@*CiLz?Xn^zz5C&IpEiO73J%|Rp1Js1GfV&yh%}h4?F^N zfED00GEMj;3nYNn?Miv2+#ly1Ao6!QN9B_4qO4g0C3YF6`sKU{+I5#Z!<7|~7nH-F z!<1W=>3VLtex_P$RA#Fu7o!OR8fBM5)ytZ1cm-9GE3vJM#U=Ga!xi7_3@=)1+!REG zEHyl9c=RkHHN+e~OwTbpt%ftrY%|Z?yVDZ$K%=T5HyM5~soE5wS1mP`vPOE1;R@ytP1p3hP42`DP=`KU*Q&E~*h$#5v|AIb z6-x?rrz`O^xhsObGZJncMRb+DW4)u7_|n!qZAlgCA?w!L>iK90OLl>2uInv+6#Wfr zh58DX&){*eGe+^q_M6xW;95POa4ji|$MkS61^5M9^E&0G=5kZ(@aNHVNtwK=nv#U4e35MIOu z5zP~nT%Q~zD7WAPh@@t?u{KG^Sd?(ghNZRL0(s72+<}yA+vOlcg^fwY$MH#qyy;Uj z=O%N#3LorMt1i}SC#y5;c(pQ9t({3kNkqO#C&h$8L!!Hjb&(E|j1GRLl}^z=B^J8x zsqh{%FHH?z7abv~aQh2K8F+|>*fSy~stc#iEUKkm=?$*EHz^PlBO;0Q634GIKiIX% zq;yi#gRoJ$M1&ZJ+y(*)Id9F@8*3akBWZ+^QnzvmlgmxAt(+W*FGw_UC6>d$@XN)E zD!V755h?-#-|CJ1lWZ{ZUlhYASdc2BSVP<;BSNUU{(J^=oU}|HO&u(%CupR1!CXN! zm(39ghAY+o%$e(&p|@)yse+LcFR|db;qur!5RnASm_$0vFf$3F)lxtuc0Ak=u7^mM z4GSKoP^3gCb#NK-cMA{_O(w72NdxkVYw-J^>s7{(_qPDnPaRY2Y^CAE?KF3S0uHKA#2thFbhN;OD@1fi2(z zzz{$+`oq9Oz^8$W0M+KtqZa=K@D%VxzyWH&Y2X&%kEq9A0-gr00-pseU>)0tm)x^B4)7hy{Sagas-Pg>n5oWJ7prQb0uq~)HgTI9948QB3kMZ@T9vemIf9%f zuCbySY|Hho0sYx3Ql=F0s64L$^@Vymb=!Yc>QWDM5A*vtR@1}O5WmYZW-wY2MR}!8 zM~$gd&UL%Kr!@^;MSAaTM#(eIqIzp5qHrxIuA8=Fk^A3aa;DI%@}h*)PmU4?RpD~u zG$hPn!V)qpbf|n9ACEf`%~W|zYsj#I3|;2$QWS%V+;%FeC?(t5PIc1qj^SV|rHC9* z;r0_9+{HvSgtvLUt9#Hcj)!7H6bad&pvES8iH7VTj!}A^R34i49* z46WO2YxHQ6p~m+Lg*6=RQte+*HMgbfYO%!Diy|dk!zXe6+gvT<6uOHXysxYj3X(iy zwZuW6#$;=+%3wbt9?8SF@Z`9Jebsjq*CPcx}*LGtQ zk|VZvSE*Y+-X=Zt2k8bTM+dC|2kZ!)cZm$LOk5&-dK%)7U~6iOj7_pc_jI-dOTGQX zrs^Fl>HNDSduVXA>Fg3CuOdasn<%o^<*DU*6LuQr1XS9Cer$kvCnL_MYsmv? zwxQ#NipIJYwCrjomze~Wy(Xi&7rD^7-sZ9YA0i{!w0zdl*6~&*u!eww7&JC2l^Y9b zh_yPLUbI+f|Ls_rtT#AcKTobvS^1+<>GA<+BwF9iq1aH5KLsxy6u(m{+%#?rxomD+6oS$6nt H3L*GkrcJQp diff --git a/cloudlb/.loadbalancers.py.swp b/cloudlb/.loadbalancers.py.swp deleted file mode 100644 index a88aee80b709a04f62aef1d05806150dc16f25e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 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 Date: Thu, 20 Sep 2012 12:54:16 -0500 Subject: [PATCH 42/55] Restoring debugging options --- cloudlb/client.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cloudlb/client.py b/cloudlb/client.py index f0c3f1e..e06cbb6 100644 --- a/cloudlb/client.py +++ b/cloudlb/client.py @@ -100,13 +100,13 @@ def _cloudlb_request(self, url, method, **kwargs): fullurl = "%s%s%s" % (self.region_account_url, url, ext) #DEBUGGING: - #if 'PYTHON_CLOUDLB_DEBUG' in os.environ: - pp = pprint.PrettyPrinter(stream=sys.stderr, indent=2) - sys.stderr.write("URL: %s\n" % (fullurl)) - sys.stderr.write("ARGS: %s\n" % (str(kwargs))) - sys.stderr.write("METHOD: %s\n" % (str(method))) - if 'body' in kwargs: - pp.pprint(json.loads(kwargs['body'])) + if 'PYTHON_CLOUDLB_DEBUG' in os.environ: + pp = pprint.PrettyPrinter(stream=sys.stderr, indent=2) + sys.stderr.write("URL: %s\n" % (fullurl)) + sys.stderr.write("ARGS: %s\n" % (str(kwargs))) + sys.stderr.write("METHOD: %s\n" % (str(method))) + if 'body' in kwargs: + pp.pprint(json.loads(kwargs['body'])) response, body = self.request(fullurl, method, **kwargs) if 'PYTHON_CLOUDLB_DEBUG' in os.environ: From 68db017690abcdceabcdfb3fa8d905c6e6dbfd7f Mon Sep 17 00:00:00 2001 From: Jessica Lucci Date: Fri, 21 Sep 2012 13:46:42 -0500 Subject: [PATCH 43/55] Creae LB method now takes in an optional list of additional create parameters --- cloudlb/.loadbalancers.py.swp | Bin 0 -> 16384 bytes cloudlb/client.pyc | Bin 5751 -> 5771 bytes cloudlb/loadbalancers.py | 11 ++++++----- cloudlb/loadbalancers.pyc | Bin 8854 -> 9038 bytes 4 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 cloudlb/.loadbalancers.py.swp diff --git a/cloudlb/.loadbalancers.py.swp b/cloudlb/.loadbalancers.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..bdbdaf88b09ab461793f4b60e1ecd703cf15d88b GIT binary patch literal 16384 zcmeHOZ)_Y#6`v-MKW#z_1tg?ECl^_F4wrKhw`z2XQ|#DH-T0s4ORD0!=k@K{xAETY zWp~esm8SiI1OkDO5L7K7l|~>02=b*s$d^>`g{mMvpz;9<5ul=?3Kbea{FC^-*`1x) z`(vl6R3Wr0{k(TOZ{BO^x8}Z0Qmi1*8i{E&e$d3 zN#G>#Zs65-G4?$0W#9rZ3+w`Zxs$Prz#>ovwgFp#-|t}Tr@$rPN#F~>U!3ET^O z7}xcBEE1?&X=yoIsXftP?!0cU_FFbiw} zuD_G9H-Mi3UkA7E&z`K_W-v8G^d+@4K5yExm=FP&t*ScYg%Pqt~o{! zlouxOBF0GkBF2KEY8t-L;QCt{wpr%mqug8KVcqK9orfM@w!#ui_#CrBZg7&prI1q6 zDAh8pCF)iPEN7|MCbPdBG4rj!Yxy;+D%9pff~RE3qKEoWCJonEw*11P5m=@8%R_cp zzu$IE;+ZJnTVcz0c@Q{Z@{GPf#O&-u#qt}rYlODv3iV2jh;PYg+NGLfTW(n7LIwt4 zn}VjlUofIkfl)PVVDKkB(I-oJs~mAdbR zp<_vl2trb>mXK7#h{kr8qY;z^(Voim=yaJ+c_BaR`73DM-C?(y(wr2yVSUvwYiV^S zyya!mqnnye+(uHmn9=fm&u?PdMPE`Uc>;@!QR@s^Z)PGBM$$fs2*$x5OVHPiD zVa{goQj{Hp7T%8Pn6@AysWuf&FQw{AsXB3gz%rb$KIyr3==qZIo18N8oVwuCi1_pp zZq#bf)WI+kTd7A-W>~aOp#5ehM6v26KM0L5C{bML=ZOa5A=#N4Z$>WoRRxn?V&M;o zG~RZhqaRl6hBcIYDssy;#iRJH76v#$Qxez;)^%HFaoikg4?-#+#Eij9ellEBelFR8 zx8(T^17=F}PP9WG^_hAl-#YrmL0r?dsHlggJl9e~rEmKBO}SvJX&Pa)NWp>PU)6S( zJo&k5+O@D+jg%#!8okalUYD*K6tQwW(+Wz4X%<{HTo=Qfn?g$gyB;F?5J@fay?f8~ zbJ&KTqcP z={kW0R}Fo^q{vr_e6?Q%VM(+K;lcqB(^oA&tYTKHWX2HAR#=_O(>*`0hD;spCB8x< zE97gw1zIy-&W?na?E@keN?T0PH8J}6tSgXoFiKL++o?DGOH-lW;Fo}#t0bN~# zbY=8JUP4u3P;*)ci~c&jwXj%0qSK2}97VN2+lwbT#wdKQu%U~rb~7+(E#@8k<#5QU z3SuhB{^Z>y8>0dmK>?O0I&$qQd58%Iu$?Ga6$PiIgqjOgD z)+pxFjv=3R=6zAZcOuRf$x=(c*WmGM$0f?_R6fS-M$_}dwnQ)8BiZ>Sags-*=~Olq zCsUT}&@&b5#UM^|I{U}DQMzAjGtKX1$Jt)VM4CZrHzCfk$!E=?0h4!bGok~oy6qopQEXyq2+T+#YX(}`(Klp1$e4aYX|(t7CC zJg3Ox2fC9_kz1#n2~!@ZflZ85XHHC4rjJff%oaJm4Oc2B#z#(8#%8ON)1%|}j}MPb zjHNh8MJaT%YSn1rRe7uxcz5n-z2UVihmYX3`O~gZ=Z9<2laIvrQq5}|$+10r-`;)L z%xj*Bthvm^%fR%EQT_i96gpp}IuZ3hzKZJw)cc_cnNj>Pk0DnNe{|w*)4d4iH z8*nS|C)D}h0zL^efd_#CupM{>HU1BQ?*rchE&?9|CV=C>R$vQ2_5aU-?*h*OF7Ny3094!4+)!PA23Q780OGtRnyQ=rOVJk>6MykX z>=LSEEj3$VAwS^g|AR5m7vvGawKURM?2j^=Aq4$?BpqGZsboZJRu4Cjto1?a^p-Wm zQ03(tc3|!4Xt?xau+*>a{YDNJQBQJ|*Hvtjrue-$t#DWDqn$R!q!y4{^N>{gn|Z z`4M?%uMnw7p#(HIe?bUu%k^^k8 z_Nyw2+Ue40X#L0|s1)r6PEY^xG|*=bkPP}j>rS0_M9wJ+gE;9=%ZciQag-A@3OyH$ z6vS}fzLCXQVn;0LHMod=^-$i zk|`bFm>tvX;Vh$6{{|Hic_Mi;n!hy;AJv5rJ+qp&CjD zQ4i!gB0WWrw$U!eXTY|pxsP5uyuAm_;#VwYgVK)=LcK$>cP4l$Pk=E_;aUk=1KruPwX&sw7h9g(OwNAXnjDsv_4 zLKOBSi=5#sBc_J+1{^y1oRW|#ulcIoBo9kRFjYQC$tbt33wqlF(SCq-WYlwel2j9^^F{+bS$?( zg8TUqe&FCCZF7rF(reMF(+RcR-QYq^jX+LW=e;29tF1AjN{x9YP8QyD8bG;;6hLm4 z-r}V;`kIbYo?$qwa=fGBG>9AAwa%t~jpOjOD1TyjYIJ%M zM@@V8Mm~?QMQkX{#mkb`DA}sUX*{W>BY$RzICdx3B%u>A-XE zquEBRMU)SQ`T~lQHct1LWD&=ZxpOK|t2|7%tLHjv@c^j!Z3R(wWOAG@#*xS}l{qW; zL5)I=40JGtIP($YG^<8{Uuzmoistm0et;8$=;t-VanuSsCVpwIe z9|;keux~6a*)__D7wqPO(nk)3<|METzgCYk5xc2xGSV!R51xxoY3K6Mc=Pj=1Lj7@ zCdMjbqq&=!4TR(NS=G|s8=ea|cdLO@UF7k}M9RHPT5A0tL)Wotcbkd1Az$liEnzk- ee(KYN-M4MjT9K04!f;N~?!zeIgd0co!G8e_*x_;j literal 0 HcmV?d00001 diff --git a/cloudlb/client.pyc b/cloudlb/client.pyc index 64fd0eb9046302215f3f8895f0ea800ce3d88728..fa8fe3e1cd2cc18c4e0c36b4fe2c52e92fc8480d 100644 GIT binary patch delta 650 zcmZ`%&ubGw7=7RDcDMU8X^d%hn_59qS+IwIUIg(jqP7Sv*5kCoEC#YH(&7Z6RY62N z40!S2UA#y@Z({xdK@j{S1TO`9s1#??N}EF2)A!!n_rCWryO&-rxYkbOUt3xI=-%)s zS4-ZTb?%|`AbjKwiVl?lLBBLk?;m`8%0~)3Yu5Gurh&2!KV-YIDMbq(0FVC zy`g#=w9?nCv>~P;nvg!Eho-KzMTY(!Bvezsg4rjTwb}Y#UsuvOGk6LeMY`c~cM5i? zxA9T@G3H&u%2=h$I=Xl3s1oGlXy|2@xuL%98Sq);6DSs~!|@z)fEA1CMYurE)aP)H z-m9PC1^S`(!i@G+JIbQlHg7`)qo;6Ltwt$5P>-T_b`yZA$5+)iCmlSD?=o**BTE+z p{I!}5cB*UCey%5wN0F0IokEH!Wezp03eD&_)n7>G2ajuit$#3TeSrV~ delta 647 zcmZ`#ziSjh7=7RD-fs5CZ0;`c_HJ`$z+hq^=@hZh^r9Araw--UgOE8qxOJPr9D&3_ z5D^>@!NSH;IplglI~)H4I~&2y!bZWF%}NqMrkQ!)oA;dDcej9bq zPFUeWrjTu@5Gp|1MA{=Wt|Ti|b`O>H@2Iz%Iy>FJb(oaKdkGI=NMu3}Mh&=y*)T-@ z)f$cnH;<)Eox}bs>9SxoSNe=o$JT1vUV!LfSVO+$RL_$b0xaLsFXK&mpg+aS^g@4& zSLmbWe4W1Q^L(9Obj4|?sBHa|zRxqdp&#*AdLy||>$d^u&t5j$O|CQjrGCa+HAsJL kMvZM+F)08Fh 128: raise InvalidLoadBalancerName("LB name is too long.") - body = {"loadBalancer": { "name": name, "port": base.getid(port), "protocol": protocol, "nodes": nodeDico, "virtualIps": vipDico, - "algorithm": algorithm, - "metadata": metadata + "algorithm": algorithm }} + if kwargs: + for key in kwargs: + body["loadBalancer"][key] = kwargs[key] + return self._create("/loadbalancers", body, "loadBalancer") def delete(self, loadbalancerid): diff --git a/cloudlb/loadbalancers.pyc b/cloudlb/loadbalancers.pyc index 5599c16186f9ae76cba472bcd7d9c9c441c9db22..5e0e49f57e63152d3182f3d1cafb9688f9a5ae45 100644 GIT binary patch delta 765 zcmYLG&ubGw6#izD?k1Z}YNIBtO`Cxz1_~a81{ytR=`U=tG%W~iJ!~^;vx!aWW{VcK zl-i0H@iO4qgNQ{CB?$gFCBMNU9 zeiS0ABDWcufXm?OY7c2E`CX{fLJJFYl&C!kECr-9Mvhd*$>|U#N+N;MRssRd{smzv zl9`;kRZwK?YA+?jSYV+qpi?EtSvY^=E3VMg0I1V-Byo`1jbOf*QYU*Rce1Cq`Qc~& zCFOP7v)6cQ-FI6}`+Awr9x`rws~c-h({FRXX8XKqH~EUgH``_s*SFZ&Nv{Agy3g!IFZkf}Db70$(RMD3zaj3o&{dT05I^$10vvxlpZhk661% z0JDo(OlL_g&+=NDbrUz(5i<3sB07t+Bn#A>%`$1 z&jfH&Vz1BdXD(gype!64=(~J zQb*rW7Lu%lfsNcK9+Z%XyqHXK@#@GTPF-1SZ7<0kC=ZG9ksSEQfq@jt$fXM(M<(2j zxT0;Y^2yxA(2M?!*5>-{^_6IKw7d7e#>4q6$aI6x`dLr)vR-FRHawZXzpPvCoYe?4 z9%ytm<}~UWTN>K}-d||(yV;n(EmSW=Qh-|~n<_?=nnplX!zPE$Nc^4C=Ga=iLG+Q^ z=YG>ezFxmdV}4oxKz(k7ZTie<_%-N@Oy`L}J`Pan;}?86T;@T;r!TzU_+@D~(m{*g tG@nw+ljeX Date: Fri, 21 Sep 2012 13:46:58 -0500 Subject: [PATCH 44/55] Removing .swp file --- cloudlb/.loadbalancers.py.swp | Bin 16384 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cloudlb/.loadbalancers.py.swp diff --git a/cloudlb/.loadbalancers.py.swp b/cloudlb/.loadbalancers.py.swp deleted file mode 100644 index bdbdaf88b09ab461793f4b60e1ecd703cf15d88b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 From 30cf8e202ee8af2881cc786bb414a7019480d1d7 Mon Sep 17 00:00:00 2001 From: Jessica Lucci Date: Tue, 25 Sep 2012 12:57:31 -0500 Subject: [PATCH 45/55] Added documentation to create_lb method --- cloudlb/loadbalancers.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 8a675b6..65864c3 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -142,7 +142,14 @@ def create(self, name, port, """ Create a new loadbalancer. - #TODO: Args + :param name: Name of the LB to create + :param port: Port number for the service you are load balancing + :param protocol: Protocol of the service which is being load balanced + :param nodes: List of nodes to be added to the LB + :param virtualIps: Type of vIP to add with creation of LB + :param algorithm: Algorithm that defines how traffic should be directed + :param kwargs: Name-based arguments for optional LB parameters (such as metadata) + :rtype: :class:'LoadBalancer' """ if not protocol in LB_PROTOCOLS: raise InvalidProtocol("''%s'' is not a valid protocol" % \ From 30d0af17fd573dcd646e9ca1ca0f079a1085ceb5 Mon Sep 17 00:00:00 2001 From: Christopher Snell Date: Tue, 20 Nov 2012 15:41:42 -0700 Subject: [PATCH 46/55] Allow statusRegex and bodyRegex to be NULL, since the Reach UI allows them to be undefined. --- cloudlb/healthmonitor.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cloudlb/healthmonitor.py b/cloudlb/healthmonitor.py index be9244c..45cfd2b 100644 --- a/cloudlb/healthmonitor.py +++ b/cloudlb/healthmonitor.py @@ -38,9 +38,8 @@ def __init__(self, type=None, #TODO: Documentation says that statusRegex or bodyRegex #can be "" but that come back NULL - if not all([path, statusRegex, bodyRegex]): - raise Exception("You need to specify a path statusregexp " + - "and bodyregexp with HTTP(S) monitor") + if not path: + raise Exception("You need to specify a path with HTTP(S) monitor") class HealthMonitorManager(SubResourceManager): From 4b693a5ef07f68b5494f0b5b5c708b631c7c44f5 Mon Sep 17 00:00:00 2001 From: Christopher Snell Date: Tue, 20 Nov 2012 20:17:31 -0700 Subject: [PATCH 47/55] Stop throwing exception on missing bodyRegex --- bin/cloudlb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/cloudlb b/bin/cloudlb index ba6ed90..b13e32a 100755 --- a/bin/cloudlb +++ b/bin/cloudlb @@ -636,8 +636,7 @@ class CLBCli(object): if config['type'] in ("HTTP", "HTTPS") and \ not all(['path' in config, - 'statusRegex' in config, - 'bodyRegex' in config]): + 'statusRegex' in config]): self._se("You are missing some arguments for %s healthMonitor" \ % config['type']) sys.exit(1) From 7a1273f3e2d500447b861a1c96e27dfe8a4fe8c0 Mon Sep 17 00:00:00 2001 From: Christopher Snell Date: Tue, 20 Nov 2012 20:18:08 -0700 Subject: [PATCH 48/55] Per API docs, bodyRegex can be NULL. Handle appropriately. --- cloudlb/healthmonitor.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cloudlb/healthmonitor.py b/cloudlb/healthmonitor.py index 45cfd2b..4804234 100644 --- a/cloudlb/healthmonitor.py +++ b/cloudlb/healthmonitor.py @@ -34,12 +34,12 @@ def __init__(self, type=None, if self.type in ("HTTP", "HTTPS"): self.path = path self.statusRegex = statusRegex - self.bodyRegex = bodyRegex + # We're only going to define self.bodyRegex is we've been passed a value for it. + if bodyRegex: + self.bodyRegex = bodyRegex - #TODO: Documentation says that statusRegex or bodyRegex - #can be "" but that come back NULL - if not path: - raise Exception("You need to specify a path with HTTP(S) monitor") + if not all([path, statusRegex]): + raise Exception("You need to specify a path and statusRegexwith HTTP(S) monitor") class HealthMonitorManager(SubResourceManager): From 22cf370e0b482491d6513cabb34968c5d2974272 Mon Sep 17 00:00:00 2001 From: Christopher Snell Date: Tue, 20 Nov 2012 20:20:03 -0700 Subject: [PATCH 49/55] correction to exception message --- cloudlb/healthmonitor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/healthmonitor.py b/cloudlb/healthmonitor.py index 4804234..8aa53f8 100644 --- a/cloudlb/healthmonitor.py +++ b/cloudlb/healthmonitor.py @@ -39,7 +39,7 @@ def __init__(self, type=None, self.bodyRegex = bodyRegex if not all([path, statusRegex]): - raise Exception("You need to specify a path and statusRegexwith HTTP(S) monitor") + raise Exception("You need to specify a path and statusRegex with HTTP(S) monitor") class HealthMonitorManager(SubResourceManager): From 6f3464cd14dc7ab40697fc86a054e5af76a07dd9 Mon Sep 17 00:00:00 2001 From: Greg Banks Date: Mon, 10 Dec 2012 11:06:22 -0800 Subject: [PATCH 50/55] iterate through node list in reverse when deleting elements --- cloudlb/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/node.py b/cloudlb/node.py index ca794c5..3753c00 100644 --- a/cloudlb/node.py +++ b/cloudlb/node.py @@ -42,7 +42,7 @@ def delete(self, nid): This DOES NOT actually remove nodes from the LB, it should be called from the node.delete() method""" - for x in range(len(self.dico)): + for x in range(len(self.dico) - 1, -1, -1): if self.dico[x].id == nid: del self.dico[x] From 6a69e27c50acbbe756eb97f13ecb7b5515be52b9 Mon Sep 17 00:00:00 2001 From: joe miller Date: Wed, 12 Dec 2012 00:09:58 +0000 Subject: [PATCH 51/55] allow new timeout attribute to be modified --- cloudlb/consts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/consts.py b/cloudlb/consts.py index cd0b616..bd6968a 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -25,7 +25,7 @@ "POP3S", "SMTP", "TCP"] # Attributed allowed to be modified on loadbalancers -LB_ATTRIBUTES_MODIFIABLE = ["name", "algorithm", "protocol", "port"] +LB_ATTRIBUTES_MODIFIABLE = ["name", "algorithm", "protocol", "port", "timeout"] # Types of VirtualIPS VIRTUALIP_TYPES = ["PUBLIC", "SERVICENET"] From 9e174573273906f8d21d585e246808b6bcbd8e46 Mon Sep 17 00:00:00 2001 From: joe miller Date: Wed, 12 Dec 2012 00:10:38 +0000 Subject: [PATCH 52/55] add new timeout attribute as an explicit default to create() method --- cloudlb/loadbalancers.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index 65864c3..bd6b74e 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -138,7 +138,7 @@ def search(self, ip): def create(self, name, port, - protocol, nodes, virtualIps, algorithm='RANDOM', **kwargs): + protocol, nodes, virtualIps, algorithm='RANDOM', timeout=30, **kwargs): """ Create a new loadbalancer. @@ -148,6 +148,7 @@ def create(self, name, port, :param nodes: List of nodes to be added to the LB :param virtualIps: Type of vIP to add with creation of LB :param algorithm: Algorithm that defines how traffic should be directed + :param timeout: Timeout (seconds) for unresponsive backend nodes :param kwargs: Name-based arguments for optional LB parameters (such as metadata) :rtype: :class:'LoadBalancer' """ @@ -166,7 +167,8 @@ def create(self, name, port, "protocol": protocol, "nodes": nodeDico, "virtualIps": vipDico, - "algorithm": algorithm + "algorithm": algorithm, + "timeout": timeout }} if kwargs: From fd10817db7a4fb81f28e523d217a8c0fa861a6aa Mon Sep 17 00:00:00 2001 From: joe miller Date: Wed, 12 Dec 2012 00:12:27 +0000 Subject: [PATCH 53/55] allow any attribute to be updated even if it was not originally returned by the rackspace api. this covers a specific case i have encountered where the rackspace api will not return the 'timeout' attribute on some loadbalancers until it is explicitly set. This happens infrequently but I have experienced it. --- cloudlb/loadbalancers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloudlb/loadbalancers.py b/cloudlb/loadbalancers.py index bd6b74e..b6d5b23 100644 --- a/cloudlb/loadbalancers.py +++ b/cloudlb/loadbalancers.py @@ -208,7 +208,7 @@ def update_node(self, loadBalancerId, nodeId, dico): def update(self, lb, originalInfo, info): ret = {} for k in LB_ATTRIBUTES_MODIFIABLE: - if k in originalInfo and info[k] != originalInfo[k]: + if k in info and info[k] != originalInfo.get(k): ret[k] = info[k] if 'protocol' in ret.keys() and ret['protocol'] not in LB_PROTOCOLS: From 647298209ab59d4ebc4aa96dbd1abc03e60cb4b9 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Sat, 3 Nov 2012 18:46:32 -0500 Subject: [PATCH 54/55] remove all the .pyc files from upstream --- cloudlb/__init__.pyc | Bin 2398 -> 0 bytes cloudlb/accesslist.pyc | Bin 2411 -> 0 bytes cloudlb/base.pyc | Bin 8687 -> 0 bytes cloudlb/cli_help.pyc | Bin 6005 -> 0 bytes cloudlb/client.pyc | Bin 5771 -> 0 bytes cloudlb/connectionlogging.pyc | Bin 1443 -> 0 bytes cloudlb/connectionthrottle.pyc | Bin 1284 -> 0 bytes cloudlb/consts.pyc | Bin 1023 -> 0 bytes cloudlb/errorpage.pyc | Bin 1366 -> 0 bytes cloudlb/errors.pyc | Bin 4330 -> 0 bytes cloudlb/healthmonitor.pyc | Bin 1750 -> 0 bytes cloudlb/loadbalancers.pyc | Bin 9038 -> 0 bytes cloudlb/node.pyc | Bin 3415 -> 0 bytes cloudlb/sessionpersistence.pyc | Bin 1339 -> 0 bytes cloudlb/ssltermination.pyc | Bin 3171 -> 0 bytes cloudlb/stats.pyc | Bin 801 -> 0 bytes cloudlb/usage.pyc | Bin 959 -> 0 bytes cloudlb/virtualip.pyc | Bin 1231 -> 0 bytes 18 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cloudlb/__init__.pyc delete mode 100644 cloudlb/accesslist.pyc delete mode 100644 cloudlb/base.pyc delete mode 100644 cloudlb/cli_help.pyc delete mode 100644 cloudlb/client.pyc delete mode 100644 cloudlb/connectionlogging.pyc delete mode 100644 cloudlb/connectionthrottle.pyc delete mode 100644 cloudlb/consts.pyc delete mode 100644 cloudlb/errorpage.pyc delete mode 100644 cloudlb/errors.pyc delete mode 100644 cloudlb/healthmonitor.pyc delete mode 100644 cloudlb/loadbalancers.pyc delete mode 100644 cloudlb/node.pyc delete mode 100644 cloudlb/sessionpersistence.pyc delete mode 100644 cloudlb/ssltermination.pyc delete mode 100644 cloudlb/stats.pyc delete mode 100644 cloudlb/usage.pyc delete mode 100644 cloudlb/virtualip.pyc diff --git a/cloudlb/__init__.pyc b/cloudlb/__init__.pyc deleted file mode 100644 index 5be660b46f1471ace8426539a3195e20b8e7167e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2398 zcmcIlOHU(55U%kHY+zwGPqH~Qha`@YfO5!%tX2zb4k#Og280w#$!s&z*aJP&&U6nf z5}ep;uK5%BdHDg!S3QFbks|gI+f(kUuBooCUfuj_srTo%!~K}*PZR$y@Yp{<5~3k! zKuLpiKv{!^4GNfVl5SGgqG7AzTcq2Rb!gbB_%`V|%I0Y}U-2E%UCMei>`|cbx8SYL zkzS;1iH1v+);#G)lr7V68GM)23Z3Ar9=#>HA^Lgvn34rL=r6K=pM&g-GgB%pwoRFw z=5j2a#g*hm{l6ZY?0Nb(KK%gtuFEgI+TPKr%3URT529B_CficWJXXa|GM6J&RGTeq z4osqEZy%+FE2ZAuuS9cDIQk(x*xehILJ)>cN;>}6ptndyn-jru2wQ$JM@ic+<|#brvv>9gq$lt>G?Q<% zI!C8Y>NYmeTnaSUongPg~G z>N5#VG!%Akg2pw%(?lfL@W9unb+T}WX$?r_39tRW-%hPLF-0a_$e{??kt%@fX}H3K zYs|61Lb-=Adpl2|ZP^wDPw;&j#2kON!Dtzz{SE}F1EN#-A8;mtVigs*3dAEHhL^vr z(6xt#dR+arLBFj58#_9%tDqbAlDQ%E$P}p?XEyceW(YHxPcvt>-+xYz_0#mAcky|E6FmLPP^0S&MkMkt!``3e*#JE1EVwreBl17=jwVr$RQ!eWqm8Z zHv_6U&&F@JbKJKfgZ6jjt@OOQchgD8-EjXLg9@}Eqjd`)QG_zINIU%D(c`aT9|Iqv k+G5CejlUeK+t4F@$Ef%;JgWl#oL#jXi%zgI{rYwDA6+W)%m4rY diff --git a/cloudlb/accesslist.pyc b/cloudlb/accesslist.pyc deleted file mode 100644 index e2879144387f9b97c528e0646c61cab99b255205..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2411 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 diff --git a/cloudlb/cli_help.pyc b/cloudlb/cli_help.pyc deleted file mode 100644 index 3e9a24b85525942f030816844baba6bdc9fd4cfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6005 zcmb_g?Qhyf7FMJS+Q%~)Wj~`mAF0Yf>1f74>yNu;M;Yj*afUkP@v&m4Na-J1vK%w^2(l3k0w3AF zAKZAeOIRUqM)Bgpb}(D?ZRd*2*`mYH$lbtp_u95^&m6o!1TU^V2Ule|5@0oDz+}5F zJe>u$DTWsp`_pUJFj1m(7N4`y#VV~=f zxo_WwbQi$_(FtZUV+K|7S1BgUd@$bVV>BY(2*d0g-hb-X7enIh1$fk7Roi8aS0Q!WxPELR`@ggJCH5Ik3 zbQPlm4$@ULv!}RaXs67%XdWzRt7rBHV5R6YUj#I80>4!`8Vq`?_wdJFtX0qKRoQ1Z z-D~@o!NLO#T9vM*Sc7rLGz_i7Lcm(}!T;v*s&Aec>bP&Vbz_xM#?s*XRMQWS2AVp) z%Od$nV6rP~pX}+}$IZ`G`uNtsHwLI*PjPSqG-{1HO7sSeAv|Nn1j+xKyo1{Qt5hDh zt|*b)Ep|PNgVf`K!Hf(?0HBIGgfb#S-fggL(0s!=i`AsJCH%jQ{{TdaV< z-<|xulUvM{kOSriT@#`-lbfH*CaM5or9e@sV1+XeS1>Neo2e~#kkZ>ZZdIam^C?RNl?qSil(aEaO{`)YO5(N6W70S|ZfpH@ zgd;S!>7>Q&*;58bh)|m@NgrS0Pp!UosQuboM~cvS;NFTm(OK*a0yQJ!jV+8+j*L_m z1ct^a*K6g(5`3{i-+k7n;y%dYX&cc@|8ivd@=t=WhKOc^R46mdjxPo5q9x0}jT*1^ z&qlSq*Wu&)vS2-EFccz9CV!+O0_%Ds+i@Tn#;m)heTp^K8KyVE;tGWupsx}th9x5w zXi-J!cFoh3su>@5n}#+xHTxf8SBaj=)8(rKXVa`Vey-NwU;SkRjJ=0AAXYu0gWK8E z7Cvx$#2~3t3!Hr&f2%Y<6bJau7Vt zql7<5IMXm>Fan|q^b0b_j(6cXyEz|m;DVU*D-OtN@C^PEoFo<5; zp3fVVSm?8xioC|TrshmoCuZHiIoY$8ak_&Qeun0V&xq(a91;;L+^qJqxi}t+lOZrP z(ZyNn!A#@a0#ZRVue;7Aqe%Dpx|N?2qA09*4Efa6obgxffc@LE^v#AA&SP?wFcNoB$FQ= zCMPrAjz*%vNLZ6rB7R<=x~y|$cBW7{o6K)$^j`16`S(nI@A+_+~PAC zUGT-a1pA5(S@0V6<0AD61jTfGGKxrB!W7PNGmCIHGmy!#k>oT8cjfBnHkw2#Kn8@z zi~Dsb7R4LpL5&qq4m%&D8_|m%+a^r8EjJR8=Q~NHgck@X6Dwg46Ik4TqUWKc^2>-! z%85-a5+%mdHu`Ks28NA<^Bl?LeE|r*EgumZ@-G6hkt_uvn2yyTQR6f;BbMUcJfMow z>A*xa?&@&ipsO(2_~N-R8L|sl!B!S-kyVNs%YDF#XmS9HQaQr14Rwky+mY`>mfgKQ zrpn+FQ`2?dx-Z!OzFNlXh3{u!Gz2(x)EWIq{Y=4rZOX-mI|e^a%tHqg>_r>`lnhU-*G>*-zdumW#V`XJ9?86BfvI=(k% oce&O1Ef@V}8n{azzlD}Bk+0!V`nFUneN$?c%BAm0&r1*g1yzV&UH||9 diff --git a/cloudlb/client.pyc b/cloudlb/client.pyc deleted file mode 100644 index fa8fe3e1cd2cc18c4e0c36b4fe2c52e92fc8480d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5771 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 diff --git a/cloudlb/consts.pyc b/cloudlb/consts.pyc deleted file mode 100644 index 4ace11bc0fc7a1ac7d6a0078a0af7022b12e248d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1023 zcma)4+fLg+5FO)?kOT;~Qs^}=RJ`C2mGV#_gku)4aAM0Br254&o-|48WTSXP)&J>R zKd(Q~*$qUmJvKfV?P7zf>31>YlcOvr(tYcoD2@mm3NbA{wp!_2 z42^U;GG=M^wV0+^U(HFK)%CWn zb7^`)o|7yBRmu59B?*g4&IgJRbV*Ihht@)Vl8*bLN5L1W@m!In zd?u6yFX}k9C2BMfF#pcBSdWG3|17uHV^%2St&|QD%XM#U);nA!KoOEe9ygyQi6Y!F zKd{}NYDFZLnAfZqiftOdWLIY7gozo2H;LSb`C^^$==Lv2y71XGi6oKlD1VEkkb63v z#Pi+IwOl6xKOzl5Et4*gb=icULv$PH5bdV7m~=aBYSf|f)o5r zKd(Q~_r}KbQYj%jnVs34d2eQx&Y#!2zfULEi8P-MelM`9Lx@yl0%^nfYcG=-&u}&9xJUbjFwdJDuJx+?{x$ooXkFqSv>-g5SIRjWP z8R;8@Lr$a;rec~c=6^CW={ET%uyoYhleDYKw%Bpl!{x+4Jg+N;BtirjhfFf6UO^69 z1m_{P67qsqDlWUJO|)105J?6`+4RH_^$MtuS9g8~jwmYKs*Iv7o@8(_35&6Sr*RhNi7Ts(q{w|s zgAA1Ht@D;4wAac`&871jaI>WH7E4D)%)lhiOgI|K<`fDb;Y;X7&hR469<;ycEEtli zJ`FVe(HNt>tw|fN{j9(n b)|XLC7cTL7Z__0Dk6>7XKPPl0+6(>yLMi6< diff --git a/cloudlb/errors.pyc b/cloudlb/errors.pyc deleted file mode 100644 index aa9595cd98a449e11f14e134b299dbcbcf869f77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4330 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 GzWWQX25c<= diff --git a/cloudlb/loadbalancers.pyc b/cloudlb/loadbalancers.pyc deleted file mode 100644 index 5e0e49f57e63152d3182f3d1cafb9688f9a5ae45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9038 zcmcgxU2_xH8Gcu?B+DNda4>Pc*n|+2Nyf}HQ_{MWfH48LMy6}0v?@f%+O;jS(kgq_ z1ZM1+rcUnKySCG-{)A3%dXc+ab$Zc1(CJKnLGNAyUFFX1r@j)*T(L+Oa0lhBcNPHH)E_@0+AFYPg@jY+#8wSsLO zldvf5lGIAl9+%p*62RjyJSpw%>7D z{1;@sa)NYw3&oY4cC;6S?ozbp?{*qH?uDjpxs?7cG^6&#*1z$u0y0Z7hGMf}f=Z5W zQz%xK>NmZ$jkPOltLw>&w&C)|hPSfx(Z<#F`i-^al@C`gFRfm+Q)Vz?rE|X#w)~rM zltj%aOipHPt5L&WYJ`nWGl;8=cDfIDtww&3jHi|5Rx_~&Dx>ActvK0hgey0*rtKi9 z@0rGSV4DgUwVpH*V_zrmdb!yQj9G1&bfFi}c0Fi>$NL2hCHMe|hNNK$1(^{DoZ@oeY zG>IlY#L*QzW)cO?wJ)+OGPka1shZq&v-B3;EZ#@Ffj5V-FX6E#A8Yag1o}80CF$3w zJou;VJ0vL-!}6Vf$nBgQ;D28Bb0qh@oW$#rII@jP<}u<$IT(`!eK}rwe@uQQ&c`|V z1`hX}RS?WGYlk)r6$zKxr5ya<>r&og^Wi%wuw#5R%TH}7IYP!bu$3Y_re68EV%t;A=*m`$3%4TPCV=3ofoZngA*-i7PsX$Wis&>TE?|sK`An?`!#B zL{O=QsW*JT4sF|Lg~r7~DoEnYJ5$a=ZpxWXp9+5Gatb>hosYuqXQ&Jc%q}?O$YCzS z-Zln+^N!5-0QWc!-j)Nf9NNJ0zCipr`vtH!kM*k_W!9sFSCnovX-ZF?-LjqX(DE%s zIXdA)blVA}moB12iv!cu%4Xz0^xooVlCU!(**uPW509bniSwHCwsSPoC4_{M#zke2 zG^{KBcP)e!zTCK4;T%tI#rs*=!c`m?K!1wG|7&>6b3Qdaj!{lc`s}nv zJZ&<~(dtLGtsnWr|H08|;YK~W8TsfGmDD)a2dv>5o5^Q!^3ZJ02{Sagqg;XD4d@tm z=@|1A{~ht(WenTE^SmKL=8ke`LZ&$~-H&s0KXRytHgup0e*R=Ts%q2^#P~XVvR=&PbBUhjsaEKarLhBJk9u9* z!g{?O`FkN>IkXye0&Ta-jzOl!2y#F~_0*I1&ay^qd$i8h(0z|J>Ob!yi%Tqs zZI4>qyUK!^F%ydsWP@=k5og{&QFQb#SI(D<rXCo2+Hh07g3r;80Mv$?2td(`K-19}6d|UKL2ZbM7}SQCh(T?L ziRjaYm{SZNX++fN2zcco5J_BZln1%hV|pIYeC{R9*Nc_ z`n`(?85(VOFmP=7i|)#@8*RDCPT(#!!-g@7cL#}c*G(c9wl)j;7UKlb#Nv}j_ct>P z=7xjRb7#!Lu1SM_o}w2~sspSzt7E6kRTwa|l=9(&XApU+ui()u4DndVm\_jFL` z!S|?b3A}vgl%y_>x_t9s@V&gmv-ElxLC%5)^vz5cMgQWK2XqHW*1TgODkjm+wq5jE5&q%AV|@`!AT#zw%Qk z>wdZuxd@0|n-PJUc9XcVwbg18zIR*QyBX~_fb>DOxV^xT^E(kF$hb%nb~W>XIwgY? zs=Vzs8)5iv|2$DAeCSeVzUx}@x{Z$SwtPJZT=KoR6ZqM_s-B*}u@4yBA&Nu9X1;&M zct66OZ2&}rud-p?WU7Z&_nA0DC&vVhxViHgYwGh9^Uk!RL56p^y1aIyNl*|qWRv=K zlW?LD_*}b=;3h%XU6S}s21bm2@-heS{}&GPCS>IpQY^>iU|jacsiF==8TgJIl(oC? z#O@!+!2|;V@E?mocitP5_>l1hWURk@%aIlWFAONi`7{c{4tOuhd4}61{6M*m;|Hp> zj2|fC2|15!-T8w_*~hv6#f%*)bJwmvIL(U2=i0PCCG-2x#FO}$k_(^wO>W^%R02pN zPK)hA8fLvh?0J5P znvG#63P>##kytwAoXQMFMr<^8v#;1>yOL%#PyQa8+`LVdL7q>`w`o*nw;YeQS5i+RO>Fy0efg>|Y zcsqDi#Q4xu&q55FYE@$V8Ed2&T@qu~l7pn^v;Hf*w1m>}-~(F!DLRG zM#xeDRuk?3e&`ctZ4jygjOn!K#|sr8K4Zz*v|88^#3B)d$T$&3q>9-aSsjlS(?zm^pUgrhch_@x)hFeEP*V z5AQTbe22xGC`M$t2HStdc(vw2E9AJ&iQF5g9m^GSGdXKEuXEiM7QClw8+Z!QUfc}o z8V73R32^-~*BhPXh&@6l(d?4_kh?IHTlJ{D z66%rO)HHuNkiPV$IELw$-k2;=m8RM}dPYObWJA(aR^X9BL)YzRB|YXc6Y{#Z19MJU z3duXl{&5su3K!?9)YZ(zqy!YN+O5td2hZmz%%! EAG!hJvH$=8 diff --git a/cloudlb/node.pyc b/cloudlb/node.pyc deleted file mode 100644 index 7e64e5945a6784e89d34b9cd46b8772f69f60644..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3415 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 diff --git a/cloudlb/stats.pyc b/cloudlb/stats.pyc deleted file mode 100644 index 3fa281b1df277cf120898ebe24e347479f201de9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 801 zcma)2!EO^V5FI-ql!{6Sq@o^>!l7tSi8yhos;cF}Wra2;_F`?kF4>i1SFv+IDyQ~u z_&k1qH{%E{NU$rvogL4-H}fVxPmX`QZ$Dc)JQIAcaMB#m6SY7^PSLHRUehDd1JRdO zQ$L|qHRZ~8fSb)W?wy}s$9+GBZZp5IC3AK7E^ORh<|im!lmpiCn zs)`xw^cuMIvFq2J?}Bx^v^-DC#52pbd5QwR{?uolVhC9hcU|7(84}hHE@T;1E|T-N z4YxE3P~j9vFA!M|xBR-WFYdnOBP5L(!jO$&tI{!m)HA#<)hlh8gU4iPS^h18vegLR z%7&UwvGjNRh?Qr>xH>&W?Ri>^DTYCYVHTN9R{833!x{0RVRcFGT>i(@4HKW>B;J$M znXW5oFWZD}>x{{~i80&Q?>+x=X&r-W*fe4Iqax8?4QfzK+$vHt_57$VRu}eepEq#_ ab|#JM(b+5=|3fX_UzGVS+2h18)4u>6w~Ge= diff --git a/cloudlb/usage.pyc b/cloudlb/usage.pyc deleted file mode 100644 index ed7e8159b4a6cb61ec8596e3b1eb3a1d688808d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 959 zcmaJ<&2HN;45nn~7Y)#1L%N>UO9r1(?AAljb?q*_1cS3-K!CxJEj4i(E0CPJ z2ibiOum{@%Y@`x2x7ij&ek8?@l%qd`{;xOl4+ZR>822k&?gE7bn4@GMIcNrRRPc*H zbEqPiN5Igr|6=%oP>al2(xMYyqqtdCrcwIr+B9-ii{;s**dbT@eO#F8viytBG+~(F zi9jx#DoE+$qWuP!1N4^w+ZZ++>?@KhfJcB$OuQyFY7y8Ak_QJ54kW#8QJ|fJjKMQl zaWWqnoS*|!DWVM<2G)VZPzFP^=}drC1QLDtwcw7!5VN)&*mOX4;FL55?kCwZ!ny%l zAk!{X51|9(oP~){vu;cotc~w;TAZ|DkOSUh$Gji4SmUo>t5~so+ z>7l3oy#9dp&DwxesS{I5`tV5#?iL^t?qiL6>JsQKWOE*N%Y}UempHCeS;aBSh7*%W zxJu5zXMMslKLJ;cX$-+*vN2TO2~ayuaO%{j>H~okHm{oypK?TXosYw*N7bBF2)0L; zORS=%wi)OFBEJg`1INaX(WeWK4>doWH~Q_s;G7evCuR8vynC;`Ut=eebo`6RQpfVHf6hK5{uzacq~d6UVb6 ztuv^Rb8y`*auq#=@t%j1{yTON{|UGpvjXUezVD0X4S5LLM6$M%0&{8Esh!@NG@2xQ@a$`-?Tqfq6x!7TS9w}4QRia$(hZ1%5?=%(f@^u>Se^0E4RsS#ZSoDto From 45ae6c1624a7018341bbdec40fbfd34962068677 Mon Sep 17 00:00:00 2001 From: Jason Straw Date: Thu, 27 Dec 2012 20:55:18 -0600 Subject: [PATCH 55/55] Update version to 0.6.0dev --- cloudlb/consts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudlb/consts.py b/cloudlb/consts.py index bd6968a..2e91846 100644 --- a/cloudlb/consts.py +++ b/cloudlb/consts.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- __author__ = "Chmouel Boudjnah " -VERSION = "0.5.1" -USER_AGENT = 'python-cloudb/%s' % VERSION +VERSION = "0.6.0dev" +USER_AGENT = 'python-cloudlb/%s' % VERSION # Default AUTH SERVER DEFAULT_AUTH_SERVER = "https://auth.api.rackspacecloud.com/v1.1/auth"