summaryrefslogtreecommitdiff
path: root/azurelinuxagent/utils/restutil.py
diff options
context:
space:
mode:
Diffstat (limited to 'azurelinuxagent/utils/restutil.py')
-rw-r--r--azurelinuxagent/utils/restutil.py154
1 files changed, 154 insertions, 0 deletions
diff --git a/azurelinuxagent/utils/restutil.py b/azurelinuxagent/utils/restutil.py
new file mode 100644
index 0000000..1015f71
--- /dev/null
+++ b/azurelinuxagent/utils/restutil.py
@@ -0,0 +1,154 @@
+# Windows Azure Linux Agent
+#
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+import time
+import platform
+import os
+import subprocess
+import azurelinuxagent.logger as logger
+import azurelinuxagent.conf as conf
+from azurelinuxagent.future import httpclient, urlparse
+
+"""
+REST api util functions
+"""
+
+RETRY_WAITING_INTERVAL = 10
+
+class HttpError(Exception):
+ pass
+
+def _parse_url(url):
+ o = urlparse(url)
+ rel_uri = o.path
+ if o.fragment:
+ rel_uri = "{0}#{1}".format(rel_uri, o.fragment)
+ if o.query:
+ rel_uri = "{0}?{1}".format(rel_uri, o.query)
+ secure = False
+ if o.scheme.lower() == "https":
+ secure = True
+ return o.hostname, o.port, secure, rel_uri
+
+def get_http_proxy():
+ """
+ Get http_proxy and https_proxy from environment variables.
+ Username and password is not supported now.
+ """
+ host = conf.get("HttpProxy.Host", None)
+ port = conf.get("HttpProxy.Port", None)
+ return (host, port)
+
+def _http_request(method, host, rel_uri, port=None, data=None, secure=False,
+ headers=None, proxy_host=None, proxy_port=None):
+ url, conn = None, None
+ if secure:
+ port = 443 if port is None else port
+ if proxy_host is not None and proxy_port is not None:
+ conn = httpclient.HTTPSConnection(proxy_host, proxy_port)
+ conn.set_tunnel(host, port)
+ #If proxy is used, full url is needed.
+ url = "https://{0}:{1}{2}".format(host, port, rel_uri)
+ else:
+ conn = httpclient.HTTPSConnection(host, port)
+ url = rel_uri
+ else:
+ port = 80 if port is None else port
+ if proxy_host is not None and proxy_port is not None:
+ conn = httpclient.HTTPConnection(proxy_host, proxy_port)
+ #If proxy is used, full url is needed.
+ url = "http://{0}:{1}{2}".format(host, port, rel_uri)
+ else:
+ conn = httpclient.HTTPConnection(host, port)
+ url = rel_uri
+ if headers == None:
+ conn.request(method, url, data)
+ else:
+ conn.request(method, url, data, headers)
+ resp = conn.getresponse()
+ return resp
+
+def http_request(method, url, data, headers=None, max_retry=3, chk_proxy=False):
+ """
+ Sending http request to server
+ On error, sleep 10 and retry max_retry times.
+ """
+ logger.verb("HTTP Req: {0} {1}", method, url)
+ logger.verb(" Data={0}", data)
+ logger.verb(" Header={0}", headers)
+ host, port, secure, rel_uri = _parse_url(url)
+
+ #Check proxy
+ proxy_host, proxy_port = (None, None)
+ if chk_proxy:
+ proxy_host, proxy_port = get_http_proxy()
+
+ #If httplib module is not built with ssl support. Fallback to http
+ if secure and not hasattr(httpclient, "HTTPSConnection"):
+ logger.warn("httplib is not built with ssl support")
+ secure = False
+
+ #If httplib module doesn't support https tunnelling. Fallback to http
+ if secure and \
+ proxy_host is not None and \
+ proxy_port is not None and \
+ not hasattr(httpclient.HTTPSConnection, "set_tunnel"):
+ logger.warn("httplib doesn't support https tunnelling(new in python 2.7)")
+ secure = False
+
+ for retry in range(0, max_retry):
+ try:
+ resp = _http_request(method, host, rel_uri, port=port, data=data,
+ secure=secure, headers=headers,
+ proxy_host=proxy_host, proxy_port=proxy_port)
+ logger.verb("HTTP Resp: Status={0}", resp.status)
+ logger.verb(" Header={0}", resp.getheaders())
+ return resp
+ except httpclient.HTTPException as e:
+ logger.warn('HTTPException {0}, args:{1}', e, repr(e.args))
+ except IOError as e:
+ logger.warn('Socket IOError {0}, args:{1}', e, repr(e.args))
+
+ if retry < max_retry - 1:
+ logger.info("Retry={0}, {1} {2}", retry, method, url)
+ time.sleep(RETRY_WAITING_INTERVAL)
+
+ raise HttpError("HTTP Err: {0} {1}".format(method, url))
+
+def http_get(url, headers=None, max_retry=3, chk_proxy=False):
+ return http_request("GET", url, data=None, headers=headers,
+ max_retry=max_retry, chk_proxy=chk_proxy)
+
+def http_head(url, headers=None, max_retry=3, chk_proxy=False):
+ return http_request("HEAD", url, None, headers=headers,
+ max_retry=max_retry, chk_proxy=chk_proxy)
+
+def http_post(url, data, headers=None, max_retry=3, chk_proxy=False):
+ return http_request("POST", url, data, headers=headers,
+ max_retry=max_retry, chk_proxy=chk_proxy)
+
+def http_put(url, data, headers=None, max_retry=3, chk_proxy=False):
+ return http_request("PUT", url, data, headers=headers,
+ max_retry=max_retry, chk_proxy=chk_proxy)
+
+def http_delete(url, headers=None, max_retry=3, chk_proxy=False):
+ return http_request("DELETE", url, None, headers=headers,
+ max_retry=max_retry, chk_proxy=chk_proxy)
+
+#End REST api util functions