mirror of
https://github.com/ansible/awx.git
synced 2026-05-15 21:37:42 -02:30
Update azure package to 0.9.0
This commit is contained in:
@@ -5,6 +5,7 @@ amqp==1.4.5 (amqp/*)
|
|||||||
ansi2html==1.0.6 (ansi2html/*)
|
ansi2html==1.0.6 (ansi2html/*)
|
||||||
anyjson==0.3.3 (anyjson/*)
|
anyjson==0.3.3 (anyjson/*)
|
||||||
argparse==1.2.1 (argparse.py, needed for Python 2.6 support)
|
argparse==1.2.1 (argparse.py, needed for Python 2.6 support)
|
||||||
|
azure==0.9.0 (azure/*)
|
||||||
Babel==1.3 (babel/*, excluded bin/pybabel)
|
Babel==1.3 (babel/*, excluded bin/pybabel)
|
||||||
billiard==3.3.0.16 (billiard/*, funtests/*, excluded _billiard.so)
|
billiard==3.3.0.16 (billiard/*, funtests/*, excluded _billiard.so)
|
||||||
boto==2.34.0 (boto/*, excluded bin/asadmin, bin/bundle_image, bin/cfadmin,
|
boto==2.34.0 (boto/*, excluded bin/asadmin, bin/bundle_image, bin/cfadmin,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
81
awx/lib/site-packages/azure/azure.pyproj
Normal file
81
awx/lib/site-packages/azure/azure.pyproj
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{25b2c65a-0553-4452-8907-8b5b17544e68}</ProjectGuid>
|
||||||
|
<ProjectHome>
|
||||||
|
</ProjectHome>
|
||||||
|
<StartupFile>storage\blobservice.py</StartupFile>
|
||||||
|
<SearchPath>..</SearchPath>
|
||||||
|
<WorkingDirectory>.</WorkingDirectory>
|
||||||
|
<OutputPath>.</OutputPath>
|
||||||
|
<Name>azure</Name>
|
||||||
|
<RootNamespace>azure</RootNamespace>
|
||||||
|
<IsWindowsApplication>False</IsWindowsApplication>
|
||||||
|
<LaunchProvider>Standard Python launcher</LaunchProvider>
|
||||||
|
<CommandLineArguments />
|
||||||
|
<InterpreterPath />
|
||||||
|
<InterpreterArguments />
|
||||||
|
<InterpreterId>{2af0f10d-7135-4994-9156-5d01c9c11b7e}</InterpreterId>
|
||||||
|
<InterpreterVersion>2.7</InterpreterVersion>
|
||||||
|
<SccProjectName>SAK</SccProjectName>
|
||||||
|
<SccProvider>SAK</SccProvider>
|
||||||
|
<SccAuxPath>SAK</SccAuxPath>
|
||||||
|
<SccLocalPath>SAK</SccLocalPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="http\batchclient.py" />
|
||||||
|
<Compile Include="http\httpclient.py" />
|
||||||
|
<Compile Include="http\requestsclient.py" />
|
||||||
|
<Compile Include="http\winhttp.py" />
|
||||||
|
<Compile Include="http\__init__.py" />
|
||||||
|
<Compile Include="servicemanagement\schedulermanagementservice.py" />
|
||||||
|
<Compile Include="servicemanagement\servicebusmanagementservice.py" />
|
||||||
|
<Compile Include="servicemanagement\servicemanagementclient.py" />
|
||||||
|
<Compile Include="servicemanagement\servicemanagementservice.py" />
|
||||||
|
<Compile Include="servicemanagement\sqldatabasemanagementservice.py" />
|
||||||
|
<Compile Include="servicemanagement\websitemanagementservice.py" />
|
||||||
|
<Compile Include="servicemanagement\__init__.py" />
|
||||||
|
<Compile Include="servicebus\servicebusservice.py" />
|
||||||
|
<Compile Include="storage\blobservice.py" />
|
||||||
|
<Compile Include="storage\queueservice.py" />
|
||||||
|
<Compile Include="storage\cloudstorageaccount.py" />
|
||||||
|
<Compile Include="storage\tableservice.py" />
|
||||||
|
<Compile Include="storage\sharedaccesssignature.py" />
|
||||||
|
<Compile Include="__init__.py" />
|
||||||
|
<Compile Include="servicebus\__init__.py" />
|
||||||
|
<Compile Include="storage\storageclient.py" />
|
||||||
|
<Compile Include="storage\__init__.py" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="http" />
|
||||||
|
<Folder Include="servicemanagement" />
|
||||||
|
<Folder Include="servicebus" />
|
||||||
|
<Folder Include="storage" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\2.6" />
|
||||||
|
<InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\2.7" />
|
||||||
|
<InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\3.3" />
|
||||||
|
<InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\3.4" />
|
||||||
|
<InterpreterReference Include="{9a7a9026-48c1-4688-9d5d-e5699d47d074}\2.7" />
|
||||||
|
<InterpreterReference Include="{9a7a9026-48c1-4688-9d5d-e5699d47d074}\3.3" />
|
||||||
|
<InterpreterReference Include="{9a7a9026-48c1-4688-9d5d-e5699d47d074}\3.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
<PtvsTargetsFile>$(VSToolsPath)\Python Tools\Microsoft.PythonTools.targets</PtvsTargetsFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Condition="Exists($(PtvsTargetsFile))" Project="$(PtvsTargetsFile)" />
|
||||||
|
<Import Condition="!Exists($(PtvsTargetsFile))" Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />
|
||||||
|
</Project>
|
||||||
@@ -1,73 +1,73 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
|
|
||||||
HTTP_RESPONSE_NO_CONTENT = 204
|
HTTP_RESPONSE_NO_CONTENT = 204
|
||||||
|
|
||||||
|
|
||||||
class HTTPError(Exception):
|
class HTTPError(Exception):
|
||||||
|
|
||||||
''' HTTP Exception when response status code >= 300 '''
|
''' HTTP Exception when response status code >= 300 '''
|
||||||
|
|
||||||
def __init__(self, status, message, respheader, respbody):
|
def __init__(self, status, message, respheader, respbody):
|
||||||
'''Creates a new HTTPError with the specified status, message,
|
'''Creates a new HTTPError with the specified status, message,
|
||||||
response headers and body'''
|
response headers and body'''
|
||||||
self.status = status
|
self.status = status
|
||||||
self.respheader = respheader
|
self.respheader = respheader
|
||||||
self.respbody = respbody
|
self.respbody = respbody
|
||||||
Exception.__init__(self, message)
|
Exception.__init__(self, message)
|
||||||
|
|
||||||
|
|
||||||
class HTTPResponse(object):
|
class HTTPResponse(object):
|
||||||
|
|
||||||
"""Represents a response from an HTTP request. An HTTPResponse has the
|
"""Represents a response from an HTTP request. An HTTPResponse has the
|
||||||
following attributes:
|
following attributes:
|
||||||
|
|
||||||
status: the status code of the response
|
status: the status code of the response
|
||||||
message: the message
|
message: the message
|
||||||
headers: the returned headers, as a list of (name, value) pairs
|
headers: the returned headers, as a list of (name, value) pairs
|
||||||
body: the body of the response
|
body: the body of the response
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, status, message, headers, body):
|
def __init__(self, status, message, headers, body):
|
||||||
self.status = status
|
self.status = status
|
||||||
self.message = message
|
self.message = message
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
self.body = body
|
self.body = body
|
||||||
|
|
||||||
|
|
||||||
class HTTPRequest(object):
|
class HTTPRequest(object):
|
||||||
|
|
||||||
'''Represents an HTTP Request. An HTTP Request consists of the following
|
'''Represents an HTTP Request. An HTTP Request consists of the following
|
||||||
attributes:
|
attributes:
|
||||||
|
|
||||||
host: the host name to connect to
|
host: the host name to connect to
|
||||||
method: the method to use to connect (string such as GET, POST, PUT, etc.)
|
method: the method to use to connect (string such as GET, POST, PUT, etc.)
|
||||||
path: the uri fragment
|
path: the uri fragment
|
||||||
query: query parameters specified as a list of (name, value) pairs
|
query: query parameters specified as a list of (name, value) pairs
|
||||||
headers: header values specified as (name, value) pairs
|
headers: header values specified as (name, value) pairs
|
||||||
body: the body of the request.
|
body: the body of the request.
|
||||||
protocol_override:
|
protocol_override:
|
||||||
specify to use this protocol instead of the global one stored in
|
specify to use this protocol instead of the global one stored in
|
||||||
_HTTPClient.
|
_HTTPClient.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.host = ''
|
self.host = ''
|
||||||
self.method = ''
|
self.method = ''
|
||||||
self.path = ''
|
self.path = ''
|
||||||
self.query = [] # list of (name, value)
|
self.query = [] # list of (name, value)
|
||||||
self.headers = [] # list of (header name, header value)
|
self.headers = [] # list of (header name, header value)
|
||||||
self.body = ''
|
self.body = ''
|
||||||
self.protocol_override = None
|
self.protocol_override = None
|
||||||
|
|||||||
@@ -1,339 +1,339 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
import sys
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from azure import (
|
from azure import (
|
||||||
_update_request_uri_query,
|
_update_request_uri_query,
|
||||||
WindowsAzureError,
|
WindowsAzureError,
|
||||||
WindowsAzureBatchOperationError,
|
WindowsAzureBatchOperationError,
|
||||||
_get_children_from_path,
|
_get_children_from_path,
|
||||||
url_unquote,
|
url_unquote,
|
||||||
_ERROR_CANNOT_FIND_PARTITION_KEY,
|
_ERROR_CANNOT_FIND_PARTITION_KEY,
|
||||||
_ERROR_CANNOT_FIND_ROW_KEY,
|
_ERROR_CANNOT_FIND_ROW_KEY,
|
||||||
_ERROR_INCORRECT_TABLE_IN_BATCH,
|
_ERROR_INCORRECT_TABLE_IN_BATCH,
|
||||||
_ERROR_INCORRECT_PARTITION_KEY_IN_BATCH,
|
_ERROR_INCORRECT_PARTITION_KEY_IN_BATCH,
|
||||||
_ERROR_DUPLICATE_ROW_KEY_IN_BATCH,
|
_ERROR_DUPLICATE_ROW_KEY_IN_BATCH,
|
||||||
_ERROR_BATCH_COMMIT_FAIL,
|
_ERROR_BATCH_COMMIT_FAIL,
|
||||||
)
|
)
|
||||||
from azure.http import HTTPError, HTTPRequest, HTTPResponse
|
from azure.http import HTTPError, HTTPRequest, HTTPResponse
|
||||||
from azure.http.httpclient import _HTTPClient
|
from azure.http.httpclient import _HTTPClient
|
||||||
from azure.storage import (
|
from azure.storage import (
|
||||||
_update_storage_table_header,
|
_update_storage_table_header,
|
||||||
METADATA_NS,
|
METADATA_NS,
|
||||||
_sign_storage_table_request,
|
_sign_storage_table_request,
|
||||||
)
|
)
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
_DATASERVICES_NS = 'http://schemas.microsoft.com/ado/2007/08/dataservices'
|
_DATASERVICES_NS = 'http://schemas.microsoft.com/ado/2007/08/dataservices'
|
||||||
|
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
def _new_boundary():
|
def _new_boundary():
|
||||||
return str(uuid.uuid1())
|
return str(uuid.uuid1())
|
||||||
else:
|
else:
|
||||||
def _new_boundary():
|
def _new_boundary():
|
||||||
return str(uuid.uuid1()).encode('utf-8')
|
return str(uuid.uuid1()).encode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
class _BatchClient(_HTTPClient):
|
class _BatchClient(_HTTPClient):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
This is the class that is used for batch operation for storage table
|
This is the class that is used for batch operation for storage table
|
||||||
service. It only supports one changeset.
|
service. It only supports one changeset.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, service_instance, account_key, account_name,
|
def __init__(self, service_instance, account_key, account_name,
|
||||||
protocol='http'):
|
protocol='http'):
|
||||||
_HTTPClient.__init__(self, service_instance, account_name=account_name,
|
_HTTPClient.__init__(self, service_instance, account_name=account_name,
|
||||||
account_key=account_key, protocol=protocol)
|
account_key=account_key, protocol=protocol)
|
||||||
self.is_batch = False
|
self.is_batch = False
|
||||||
self.batch_requests = []
|
self.batch_requests = []
|
||||||
self.batch_table = ''
|
self.batch_table = ''
|
||||||
self.batch_partition_key = ''
|
self.batch_partition_key = ''
|
||||||
self.batch_row_keys = []
|
self.batch_row_keys = []
|
||||||
|
|
||||||
def get_request_table(self, request):
|
def get_request_table(self, request):
|
||||||
'''
|
'''
|
||||||
Extracts table name from request.uri. The request.uri has either
|
Extracts table name from request.uri. The request.uri has either
|
||||||
"/mytable(...)" or "/mytable" format.
|
"/mytable(...)" or "/mytable" format.
|
||||||
|
|
||||||
request: the request to insert, update or delete entity
|
request: the request to insert, update or delete entity
|
||||||
'''
|
'''
|
||||||
if '(' in request.path:
|
if '(' in request.path:
|
||||||
pos = request.path.find('(')
|
pos = request.path.find('(')
|
||||||
return request.path[1:pos]
|
return request.path[1:pos]
|
||||||
else:
|
else:
|
||||||
return request.path[1:]
|
return request.path[1:]
|
||||||
|
|
||||||
def get_request_partition_key(self, request):
|
def get_request_partition_key(self, request):
|
||||||
'''
|
'''
|
||||||
Extracts PartitionKey from request.body if it is a POST request or from
|
Extracts PartitionKey from request.body if it is a POST request or from
|
||||||
request.path if it is not a POST request. Only insert operation request
|
request.path if it is not a POST request. Only insert operation request
|
||||||
is a POST request and the PartitionKey is in the request body.
|
is a POST request and the PartitionKey is in the request body.
|
||||||
|
|
||||||
request: the request to insert, update or delete entity
|
request: the request to insert, update or delete entity
|
||||||
'''
|
'''
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
doc = minidom.parseString(request.body)
|
doc = minidom.parseString(request.body)
|
||||||
part_key = _get_children_from_path(
|
part_key = _get_children_from_path(
|
||||||
doc, 'entry', 'content', (METADATA_NS, 'properties'),
|
doc, 'entry', 'content', (METADATA_NS, 'properties'),
|
||||||
(_DATASERVICES_NS, 'PartitionKey'))
|
(_DATASERVICES_NS, 'PartitionKey'))
|
||||||
if not part_key:
|
if not part_key:
|
||||||
raise WindowsAzureError(_ERROR_CANNOT_FIND_PARTITION_KEY)
|
raise WindowsAzureError(_ERROR_CANNOT_FIND_PARTITION_KEY)
|
||||||
return part_key[0].firstChild.nodeValue
|
return part_key[0].firstChild.nodeValue
|
||||||
else:
|
else:
|
||||||
uri = url_unquote(request.path)
|
uri = url_unquote(request.path)
|
||||||
pos1 = uri.find('PartitionKey=\'')
|
pos1 = uri.find('PartitionKey=\'')
|
||||||
pos2 = uri.find('\',', pos1)
|
pos2 = uri.find('\',', pos1)
|
||||||
if pos1 == -1 or pos2 == -1:
|
if pos1 == -1 or pos2 == -1:
|
||||||
raise WindowsAzureError(_ERROR_CANNOT_FIND_PARTITION_KEY)
|
raise WindowsAzureError(_ERROR_CANNOT_FIND_PARTITION_KEY)
|
||||||
return uri[pos1 + len('PartitionKey=\''):pos2]
|
return uri[pos1 + len('PartitionKey=\''):pos2]
|
||||||
|
|
||||||
def get_request_row_key(self, request):
|
def get_request_row_key(self, request):
|
||||||
'''
|
'''
|
||||||
Extracts RowKey from request.body if it is a POST request or from
|
Extracts RowKey from request.body if it is a POST request or from
|
||||||
request.path if it is not a POST request. Only insert operation request
|
request.path if it is not a POST request. Only insert operation request
|
||||||
is a POST request and the Rowkey is in the request body.
|
is a POST request and the Rowkey is in the request body.
|
||||||
|
|
||||||
request: the request to insert, update or delete entity
|
request: the request to insert, update or delete entity
|
||||||
'''
|
'''
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
doc = minidom.parseString(request.body)
|
doc = minidom.parseString(request.body)
|
||||||
row_key = _get_children_from_path(
|
row_key = _get_children_from_path(
|
||||||
doc, 'entry', 'content', (METADATA_NS, 'properties'),
|
doc, 'entry', 'content', (METADATA_NS, 'properties'),
|
||||||
(_DATASERVICES_NS, 'RowKey'))
|
(_DATASERVICES_NS, 'RowKey'))
|
||||||
if not row_key:
|
if not row_key:
|
||||||
raise WindowsAzureError(_ERROR_CANNOT_FIND_ROW_KEY)
|
raise WindowsAzureError(_ERROR_CANNOT_FIND_ROW_KEY)
|
||||||
return row_key[0].firstChild.nodeValue
|
return row_key[0].firstChild.nodeValue
|
||||||
else:
|
else:
|
||||||
uri = url_unquote(request.path)
|
uri = url_unquote(request.path)
|
||||||
pos1 = uri.find('RowKey=\'')
|
pos1 = uri.find('RowKey=\'')
|
||||||
pos2 = uri.find('\')', pos1)
|
pos2 = uri.find('\')', pos1)
|
||||||
if pos1 == -1 or pos2 == -1:
|
if pos1 == -1 or pos2 == -1:
|
||||||
raise WindowsAzureError(_ERROR_CANNOT_FIND_ROW_KEY)
|
raise WindowsAzureError(_ERROR_CANNOT_FIND_ROW_KEY)
|
||||||
row_key = uri[pos1 + len('RowKey=\''):pos2]
|
row_key = uri[pos1 + len('RowKey=\''):pos2]
|
||||||
return row_key
|
return row_key
|
||||||
|
|
||||||
def validate_request_table(self, request):
|
def validate_request_table(self, request):
|
||||||
'''
|
'''
|
||||||
Validates that all requests have the same table name. Set the table
|
Validates that all requests have the same table name. Set the table
|
||||||
name if it is the first request for the batch operation.
|
name if it is the first request for the batch operation.
|
||||||
|
|
||||||
request: the request to insert, update or delete entity
|
request: the request to insert, update or delete entity
|
||||||
'''
|
'''
|
||||||
if self.batch_table:
|
if self.batch_table:
|
||||||
if self.get_request_table(request) != self.batch_table:
|
if self.get_request_table(request) != self.batch_table:
|
||||||
raise WindowsAzureError(_ERROR_INCORRECT_TABLE_IN_BATCH)
|
raise WindowsAzureError(_ERROR_INCORRECT_TABLE_IN_BATCH)
|
||||||
else:
|
else:
|
||||||
self.batch_table = self.get_request_table(request)
|
self.batch_table = self.get_request_table(request)
|
||||||
|
|
||||||
def validate_request_partition_key(self, request):
|
def validate_request_partition_key(self, request):
|
||||||
'''
|
'''
|
||||||
Validates that all requests have the same PartitiionKey. Set the
|
Validates that all requests have the same PartitiionKey. Set the
|
||||||
PartitionKey if it is the first request for the batch operation.
|
PartitionKey if it is the first request for the batch operation.
|
||||||
|
|
||||||
request: the request to insert, update or delete entity
|
request: the request to insert, update or delete entity
|
||||||
'''
|
'''
|
||||||
if self.batch_partition_key:
|
if self.batch_partition_key:
|
||||||
if self.get_request_partition_key(request) != \
|
if self.get_request_partition_key(request) != \
|
||||||
self.batch_partition_key:
|
self.batch_partition_key:
|
||||||
raise WindowsAzureError(_ERROR_INCORRECT_PARTITION_KEY_IN_BATCH)
|
raise WindowsAzureError(_ERROR_INCORRECT_PARTITION_KEY_IN_BATCH)
|
||||||
else:
|
else:
|
||||||
self.batch_partition_key = self.get_request_partition_key(request)
|
self.batch_partition_key = self.get_request_partition_key(request)
|
||||||
|
|
||||||
def validate_request_row_key(self, request):
|
def validate_request_row_key(self, request):
|
||||||
'''
|
'''
|
||||||
Validates that all requests have the different RowKey and adds RowKey
|
Validates that all requests have the different RowKey and adds RowKey
|
||||||
to existing RowKey list.
|
to existing RowKey list.
|
||||||
|
|
||||||
request: the request to insert, update or delete entity
|
request: the request to insert, update or delete entity
|
||||||
'''
|
'''
|
||||||
if self.batch_row_keys:
|
if self.batch_row_keys:
|
||||||
if self.get_request_row_key(request) in self.batch_row_keys:
|
if self.get_request_row_key(request) in self.batch_row_keys:
|
||||||
raise WindowsAzureError(_ERROR_DUPLICATE_ROW_KEY_IN_BATCH)
|
raise WindowsAzureError(_ERROR_DUPLICATE_ROW_KEY_IN_BATCH)
|
||||||
else:
|
else:
|
||||||
self.batch_row_keys.append(self.get_request_row_key(request))
|
self.batch_row_keys.append(self.get_request_row_key(request))
|
||||||
|
|
||||||
def begin_batch(self):
|
def begin_batch(self):
|
||||||
'''
|
'''
|
||||||
Starts the batch operation. Intializes the batch variables
|
Starts the batch operation. Intializes the batch variables
|
||||||
|
|
||||||
is_batch: batch operation flag.
|
is_batch: batch operation flag.
|
||||||
batch_table: the table name of the batch operation
|
batch_table: the table name of the batch operation
|
||||||
batch_partition_key: the PartitionKey of the batch requests.
|
batch_partition_key: the PartitionKey of the batch requests.
|
||||||
batch_row_keys: the RowKey list of adding requests.
|
batch_row_keys: the RowKey list of adding requests.
|
||||||
batch_requests: the list of the requests.
|
batch_requests: the list of the requests.
|
||||||
'''
|
'''
|
||||||
self.is_batch = True
|
self.is_batch = True
|
||||||
self.batch_table = ''
|
self.batch_table = ''
|
||||||
self.batch_partition_key = ''
|
self.batch_partition_key = ''
|
||||||
self.batch_row_keys = []
|
self.batch_row_keys = []
|
||||||
self.batch_requests = []
|
self.batch_requests = []
|
||||||
|
|
||||||
def insert_request_to_batch(self, request):
|
def insert_request_to_batch(self, request):
|
||||||
'''
|
'''
|
||||||
Adds request to batch operation.
|
Adds request to batch operation.
|
||||||
|
|
||||||
request: the request to insert, update or delete entity
|
request: the request to insert, update or delete entity
|
||||||
'''
|
'''
|
||||||
self.validate_request_table(request)
|
self.validate_request_table(request)
|
||||||
self.validate_request_partition_key(request)
|
self.validate_request_partition_key(request)
|
||||||
self.validate_request_row_key(request)
|
self.validate_request_row_key(request)
|
||||||
self.batch_requests.append(request)
|
self.batch_requests.append(request)
|
||||||
|
|
||||||
def commit_batch(self):
|
def commit_batch(self):
|
||||||
''' Resets batch flag and commits the batch requests. '''
|
''' Resets batch flag and commits the batch requests. '''
|
||||||
if self.is_batch:
|
if self.is_batch:
|
||||||
self.is_batch = False
|
self.is_batch = False
|
||||||
self.commit_batch_requests()
|
self.commit_batch_requests()
|
||||||
|
|
||||||
def commit_batch_requests(self):
|
def commit_batch_requests(self):
|
||||||
''' Commits the batch requests. '''
|
''' Commits the batch requests. '''
|
||||||
|
|
||||||
batch_boundary = b'batch_' + _new_boundary()
|
batch_boundary = b'batch_' + _new_boundary()
|
||||||
changeset_boundary = b'changeset_' + _new_boundary()
|
changeset_boundary = b'changeset_' + _new_boundary()
|
||||||
|
|
||||||
# Commits batch only the requests list is not empty.
|
# Commits batch only the requests list is not empty.
|
||||||
if self.batch_requests:
|
if self.batch_requests:
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.host = self.batch_requests[0].host
|
request.host = self.batch_requests[0].host
|
||||||
request.path = '/$batch'
|
request.path = '/$batch'
|
||||||
request.headers = [
|
request.headers = [
|
||||||
('Content-Type', 'multipart/mixed; boundary=' + \
|
('Content-Type', 'multipart/mixed; boundary=' + \
|
||||||
batch_boundary.decode('utf-8')),
|
batch_boundary.decode('utf-8')),
|
||||||
('Accept', 'application/atom+xml,application/xml'),
|
('Accept', 'application/atom+xml,application/xml'),
|
||||||
('Accept-Charset', 'UTF-8')]
|
('Accept-Charset', 'UTF-8')]
|
||||||
|
|
||||||
request.body = b'--' + batch_boundary + b'\n'
|
request.body = b'--' + batch_boundary + b'\n'
|
||||||
request.body += b'Content-Type: multipart/mixed; boundary='
|
request.body += b'Content-Type: multipart/mixed; boundary='
|
||||||
request.body += changeset_boundary + b'\n\n'
|
request.body += changeset_boundary + b'\n\n'
|
||||||
|
|
||||||
content_id = 1
|
content_id = 1
|
||||||
|
|
||||||
# Adds each request body to the POST data.
|
# Adds each request body to the POST data.
|
||||||
for batch_request in self.batch_requests:
|
for batch_request in self.batch_requests:
|
||||||
request.body += b'--' + changeset_boundary + b'\n'
|
request.body += b'--' + changeset_boundary + b'\n'
|
||||||
request.body += b'Content-Type: application/http\n'
|
request.body += b'Content-Type: application/http\n'
|
||||||
request.body += b'Content-Transfer-Encoding: binary\n\n'
|
request.body += b'Content-Transfer-Encoding: binary\n\n'
|
||||||
request.body += batch_request.method.encode('utf-8')
|
request.body += batch_request.method.encode('utf-8')
|
||||||
request.body += b' http://'
|
request.body += b' http://'
|
||||||
request.body += batch_request.host.encode('utf-8')
|
request.body += batch_request.host.encode('utf-8')
|
||||||
request.body += batch_request.path.encode('utf-8')
|
request.body += batch_request.path.encode('utf-8')
|
||||||
request.body += b' HTTP/1.1\n'
|
request.body += b' HTTP/1.1\n'
|
||||||
request.body += b'Content-ID: '
|
request.body += b'Content-ID: '
|
||||||
request.body += str(content_id).encode('utf-8') + b'\n'
|
request.body += str(content_id).encode('utf-8') + b'\n'
|
||||||
content_id += 1
|
content_id += 1
|
||||||
|
|
||||||
# Add different headers for different type requests.
|
# Add different headers for different type requests.
|
||||||
if not batch_request.method == 'DELETE':
|
if not batch_request.method == 'DELETE':
|
||||||
request.body += \
|
request.body += \
|
||||||
b'Content-Type: application/atom+xml;type=entry\n'
|
b'Content-Type: application/atom+xml;type=entry\n'
|
||||||
for name, value in batch_request.headers:
|
for name, value in batch_request.headers:
|
||||||
if name == 'If-Match':
|
if name == 'If-Match':
|
||||||
request.body += name.encode('utf-8') + b': '
|
request.body += name.encode('utf-8') + b': '
|
||||||
request.body += value.encode('utf-8') + b'\n'
|
request.body += value.encode('utf-8') + b'\n'
|
||||||
break
|
break
|
||||||
request.body += b'Content-Length: '
|
request.body += b'Content-Length: '
|
||||||
request.body += str(len(batch_request.body)).encode('utf-8')
|
request.body += str(len(batch_request.body)).encode('utf-8')
|
||||||
request.body += b'\n\n'
|
request.body += b'\n\n'
|
||||||
request.body += batch_request.body + b'\n'
|
request.body += batch_request.body + b'\n'
|
||||||
else:
|
else:
|
||||||
for name, value in batch_request.headers:
|
for name, value in batch_request.headers:
|
||||||
# If-Match should be already included in
|
# If-Match should be already included in
|
||||||
# batch_request.headers, but in case it is missing,
|
# batch_request.headers, but in case it is missing,
|
||||||
# just add it.
|
# just add it.
|
||||||
if name == 'If-Match':
|
if name == 'If-Match':
|
||||||
request.body += name.encode('utf-8') + b': '
|
request.body += name.encode('utf-8') + b': '
|
||||||
request.body += value.encode('utf-8') + b'\n\n'
|
request.body += value.encode('utf-8') + b'\n\n'
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
request.body += b'If-Match: *\n\n'
|
request.body += b'If-Match: *\n\n'
|
||||||
|
|
||||||
request.body += b'--' + changeset_boundary + b'--' + b'\n'
|
request.body += b'--' + changeset_boundary + b'--' + b'\n'
|
||||||
request.body += b'--' + batch_boundary + b'--'
|
request.body += b'--' + batch_boundary + b'--'
|
||||||
|
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
request.path, request.query = _update_request_uri_query(request)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
auth = _sign_storage_table_request(request,
|
auth = _sign_storage_table_request(request,
|
||||||
self.account_name,
|
self.account_name,
|
||||||
self.account_key)
|
self.account_key)
|
||||||
request.headers.append(('Authorization', auth))
|
request.headers.append(('Authorization', auth))
|
||||||
|
|
||||||
# Submit the whole request as batch request.
|
# Submit the whole request as batch request.
|
||||||
response = self.perform_request(request)
|
response = self.perform_request(request)
|
||||||
if response.status >= 300:
|
if response.status >= 300:
|
||||||
raise HTTPError(response.status,
|
raise HTTPError(response.status,
|
||||||
_ERROR_BATCH_COMMIT_FAIL,
|
_ERROR_BATCH_COMMIT_FAIL,
|
||||||
self.respheader,
|
self.respheader,
|
||||||
response.body)
|
response.body)
|
||||||
|
|
||||||
# http://www.odata.org/documentation/odata-version-2-0/batch-processing/
|
# http://www.odata.org/documentation/odata-version-2-0/batch-processing/
|
||||||
# The body of a ChangeSet response is either a response for all the
|
# The body of a ChangeSet response is either a response for all the
|
||||||
# successfully processed change request within the ChangeSet,
|
# successfully processed change request within the ChangeSet,
|
||||||
# formatted exactly as it would have appeared outside of a batch,
|
# formatted exactly as it would have appeared outside of a batch,
|
||||||
# or a single response indicating a failure of the entire ChangeSet.
|
# or a single response indicating a failure of the entire ChangeSet.
|
||||||
responses = self._parse_batch_response(response.body)
|
responses = self._parse_batch_response(response.body)
|
||||||
if responses and responses[0].status >= 300:
|
if responses and responses[0].status >= 300:
|
||||||
self._report_batch_error(responses[0])
|
self._report_batch_error(responses[0])
|
||||||
|
|
||||||
def cancel_batch(self):
|
def cancel_batch(self):
|
||||||
''' Resets the batch flag. '''
|
''' Resets the batch flag. '''
|
||||||
self.is_batch = False
|
self.is_batch = False
|
||||||
|
|
||||||
def _parse_batch_response(self, body):
|
def _parse_batch_response(self, body):
|
||||||
parts = body.split(b'--changesetresponse_')
|
parts = body.split(b'--changesetresponse_')
|
||||||
|
|
||||||
responses = []
|
responses = []
|
||||||
for part in parts:
|
for part in parts:
|
||||||
httpLocation = part.find(b'HTTP/')
|
httpLocation = part.find(b'HTTP/')
|
||||||
if httpLocation > 0:
|
if httpLocation > 0:
|
||||||
response = self._parse_batch_response_part(part[httpLocation:])
|
response = self._parse_batch_response_part(part[httpLocation:])
|
||||||
responses.append(response)
|
responses.append(response)
|
||||||
|
|
||||||
return responses
|
return responses
|
||||||
|
|
||||||
def _parse_batch_response_part(self, part):
|
def _parse_batch_response_part(self, part):
|
||||||
lines = part.splitlines();
|
lines = part.splitlines();
|
||||||
|
|
||||||
# First line is the HTTP status/reason
|
# First line is the HTTP status/reason
|
||||||
status, _, reason = lines[0].partition(b' ')[2].partition(b' ')
|
status, _, reason = lines[0].partition(b' ')[2].partition(b' ')
|
||||||
|
|
||||||
# Followed by headers and body
|
# Followed by headers and body
|
||||||
headers = []
|
headers = []
|
||||||
body = b''
|
body = b''
|
||||||
isBody = False
|
isBody = False
|
||||||
for line in lines[1:]:
|
for line in lines[1:]:
|
||||||
if line == b'' and not isBody:
|
if line == b'' and not isBody:
|
||||||
isBody = True
|
isBody = True
|
||||||
elif isBody:
|
elif isBody:
|
||||||
body += line
|
body += line
|
||||||
else:
|
else:
|
||||||
headerName, _, headerVal = line.partition(b':')
|
headerName, _, headerVal = line.partition(b':')
|
||||||
headers.append((headerName.lower(), headerVal))
|
headers.append((headerName.lower(), headerVal))
|
||||||
|
|
||||||
return HTTPResponse(int(status), reason.strip(), headers, body)
|
return HTTPResponse(int(status), reason.strip(), headers, body)
|
||||||
|
|
||||||
def _report_batch_error(self, response):
|
def _report_batch_error(self, response):
|
||||||
xml = response.body.decode('utf-8')
|
xml = response.body.decode('utf-8')
|
||||||
doc = minidom.parseString(xml)
|
doc = minidom.parseString(xml)
|
||||||
|
|
||||||
n = _get_children_from_path(doc, (METADATA_NS, 'error'), 'code')
|
n = _get_children_from_path(doc, (METADATA_NS, 'error'), 'code')
|
||||||
code = n[0].firstChild.nodeValue if n and n[0].firstChild else ''
|
code = n[0].firstChild.nodeValue if n and n[0].firstChild else ''
|
||||||
|
|
||||||
n = _get_children_from_path(doc, (METADATA_NS, 'error'), 'message')
|
n = _get_children_from_path(doc, (METADATA_NS, 'error'), 'message')
|
||||||
message = n[0].firstChild.nodeValue if n and n[0].firstChild else xml
|
message = n[0].firstChild.nodeValue if n and n[0].firstChild else xml
|
||||||
|
|
||||||
raise WindowsAzureBatchOperationError(message, code)
|
raise WindowsAzureBatchOperationError(message, code)
|
||||||
|
|||||||
@@ -1,223 +1,251 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
import base64
|
import base64
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
from httplib import (
|
from httplib import (
|
||||||
HTTPSConnection,
|
HTTPSConnection,
|
||||||
HTTPConnection,
|
HTTPConnection,
|
||||||
HTTP_PORT,
|
HTTP_PORT,
|
||||||
HTTPS_PORT,
|
HTTPS_PORT,
|
||||||
)
|
)
|
||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
else:
|
else:
|
||||||
from http.client import (
|
from http.client import (
|
||||||
HTTPSConnection,
|
HTTPSConnection,
|
||||||
HTTPConnection,
|
HTTPConnection,
|
||||||
HTTP_PORT,
|
HTTP_PORT,
|
||||||
HTTPS_PORT,
|
HTTPS_PORT,
|
||||||
)
|
)
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from azure.http import HTTPError, HTTPResponse
|
from azure.http import HTTPError, HTTPResponse
|
||||||
from azure import _USER_AGENT_STRING, _update_request_uri_query
|
from azure import _USER_AGENT_STRING, _update_request_uri_query
|
||||||
|
|
||||||
|
DEBUG_REQUESTS = False
|
||||||
class _HTTPClient(object):
|
DEBUG_RESPONSES = False
|
||||||
|
|
||||||
'''
|
class _HTTPClient(object):
|
||||||
Takes the request and sends it to cloud service and returns the response.
|
|
||||||
'''
|
'''
|
||||||
|
Takes the request and sends it to cloud service and returns the response.
|
||||||
def __init__(self, service_instance, cert_file=None, account_name=None,
|
'''
|
||||||
account_key=None, service_namespace=None, issuer=None,
|
|
||||||
protocol='https'):
|
def __init__(self, service_instance, cert_file=None, account_name=None,
|
||||||
'''
|
account_key=None, protocol='https', request_session=None):
|
||||||
service_instance: service client instance.
|
'''
|
||||||
cert_file:
|
service_instance: service client instance.
|
||||||
certificate file name/location. This is only used in hosted
|
cert_file:
|
||||||
service management.
|
certificate file name/location. This is only used in hosted
|
||||||
account_name: the storage account.
|
service management.
|
||||||
account_key:
|
account_name: the storage account.
|
||||||
the storage account access key for storage services or servicebus
|
account_key:
|
||||||
access key for service bus service.
|
the storage account access key.
|
||||||
service_namespace: the service namespace for service bus.
|
request_session:
|
||||||
issuer: the issuer for service bus service.
|
session object created with requests library (or compatible).
|
||||||
'''
|
'''
|
||||||
self.service_instance = service_instance
|
self.service_instance = service_instance
|
||||||
self.status = None
|
self.status = None
|
||||||
self.respheader = None
|
self.respheader = None
|
||||||
self.message = None
|
self.message = None
|
||||||
self.cert_file = cert_file
|
self.cert_file = cert_file
|
||||||
self.account_name = account_name
|
self.account_name = account_name
|
||||||
self.account_key = account_key
|
self.account_key = account_key
|
||||||
self.service_namespace = service_namespace
|
self.protocol = protocol
|
||||||
self.issuer = issuer
|
self.proxy_host = None
|
||||||
self.protocol = protocol
|
self.proxy_port = None
|
||||||
self.proxy_host = None
|
self.proxy_user = None
|
||||||
self.proxy_port = None
|
self.proxy_password = None
|
||||||
self.proxy_user = None
|
self.request_session = request_session
|
||||||
self.proxy_password = None
|
if request_session:
|
||||||
self.use_httplib = self.should_use_httplib()
|
self.use_httplib = True
|
||||||
|
else:
|
||||||
def should_use_httplib(self):
|
self.use_httplib = self.should_use_httplib()
|
||||||
if sys.platform.lower().startswith('win') and self.cert_file:
|
|
||||||
# On Windows, auto-detect between Windows Store Certificate
|
def should_use_httplib(self):
|
||||||
# (winhttp) and OpenSSL .pem certificate file (httplib).
|
if sys.platform.lower().startswith('win') and self.cert_file:
|
||||||
#
|
# On Windows, auto-detect between Windows Store Certificate
|
||||||
# We used to only support certificates installed in the Windows
|
# (winhttp) and OpenSSL .pem certificate file (httplib).
|
||||||
# Certificate Store.
|
#
|
||||||
# cert_file example: CURRENT_USER\my\CertificateName
|
# We used to only support certificates installed in the Windows
|
||||||
#
|
# Certificate Store.
|
||||||
# We now support using an OpenSSL .pem certificate file,
|
# cert_file example: CURRENT_USER\my\CertificateName
|
||||||
# for a consistent experience across all platforms.
|
#
|
||||||
# cert_file example: account\certificate.pem
|
# We now support using an OpenSSL .pem certificate file,
|
||||||
#
|
# for a consistent experience across all platforms.
|
||||||
# When using OpenSSL .pem certificate file on Windows, make sure
|
# cert_file example: account\certificate.pem
|
||||||
# you are on CPython 2.7.4 or later.
|
#
|
||||||
|
# When using OpenSSL .pem certificate file on Windows, make sure
|
||||||
# If it's not an existing file on disk, then treat it as a path in
|
# you are on CPython 2.7.4 or later.
|
||||||
# the Windows Certificate Store, which means we can't use httplib.
|
|
||||||
if not os.path.isfile(self.cert_file):
|
# If it's not an existing file on disk, then treat it as a path in
|
||||||
return False
|
# the Windows Certificate Store, which means we can't use httplib.
|
||||||
|
if not os.path.isfile(self.cert_file):
|
||||||
return True
|
return False
|
||||||
|
|
||||||
def set_proxy(self, host, port, user, password):
|
return True
|
||||||
'''
|
|
||||||
Sets the proxy server host and port for the HTTP CONNECT Tunnelling.
|
def set_proxy(self, host, port, user, password):
|
||||||
|
'''
|
||||||
host: Address of the proxy. Ex: '192.168.0.100'
|
Sets the proxy server host and port for the HTTP CONNECT Tunnelling.
|
||||||
port: Port of the proxy. Ex: 6000
|
|
||||||
user: User for proxy authorization.
|
host: Address of the proxy. Ex: '192.168.0.100'
|
||||||
password: Password for proxy authorization.
|
port: Port of the proxy. Ex: 6000
|
||||||
'''
|
user: User for proxy authorization.
|
||||||
self.proxy_host = host
|
password: Password for proxy authorization.
|
||||||
self.proxy_port = port
|
'''
|
||||||
self.proxy_user = user
|
self.proxy_host = host
|
||||||
self.proxy_password = password
|
self.proxy_port = port
|
||||||
|
self.proxy_user = user
|
||||||
def get_connection(self, request):
|
self.proxy_password = password
|
||||||
''' Create connection for the request. '''
|
|
||||||
protocol = request.protocol_override \
|
def get_uri(self, request):
|
||||||
if request.protocol_override else self.protocol
|
''' Return the target uri for the request.'''
|
||||||
target_host = request.host
|
protocol = request.protocol_override \
|
||||||
target_port = HTTP_PORT if protocol == 'http' else HTTPS_PORT
|
if request.protocol_override else self.protocol
|
||||||
|
port = HTTP_PORT if protocol == 'http' else HTTPS_PORT
|
||||||
if not self.use_httplib:
|
return protocol + '://' + request.host + ':' + str(port) + request.path
|
||||||
import azure.http.winhttp
|
|
||||||
connection = azure.http.winhttp._HTTPConnection(
|
def get_connection(self, request):
|
||||||
target_host, cert_file=self.cert_file, protocol=protocol)
|
''' Create connection for the request. '''
|
||||||
proxy_host = self.proxy_host
|
protocol = request.protocol_override \
|
||||||
proxy_port = self.proxy_port
|
if request.protocol_override else self.protocol
|
||||||
else:
|
target_host = request.host
|
||||||
if ':' in target_host:
|
target_port = HTTP_PORT if protocol == 'http' else HTTPS_PORT
|
||||||
target_host, _, target_port = target_host.rpartition(':')
|
|
||||||
if self.proxy_host:
|
if self.request_session:
|
||||||
proxy_host = target_host
|
import azure.http.requestsclient
|
||||||
proxy_port = target_port
|
connection = azure.http.requestsclient._RequestsConnection(
|
||||||
host = self.proxy_host
|
target_host, protocol, self.request_session)
|
||||||
port = self.proxy_port
|
#TODO: proxy stuff
|
||||||
else:
|
elif not self.use_httplib:
|
||||||
host = target_host
|
import azure.http.winhttp
|
||||||
port = target_port
|
connection = azure.http.winhttp._HTTPConnection(
|
||||||
|
target_host, cert_file=self.cert_file, protocol=protocol)
|
||||||
if protocol == 'http':
|
proxy_host = self.proxy_host
|
||||||
connection = HTTPConnection(host, int(port))
|
proxy_port = self.proxy_port
|
||||||
else:
|
else:
|
||||||
connection = HTTPSConnection(
|
if ':' in target_host:
|
||||||
host, int(port), cert_file=self.cert_file)
|
target_host, _, target_port = target_host.rpartition(':')
|
||||||
|
if self.proxy_host:
|
||||||
if self.proxy_host:
|
proxy_host = target_host
|
||||||
headers = None
|
proxy_port = target_port
|
||||||
if self.proxy_user and self.proxy_password:
|
host = self.proxy_host
|
||||||
auth = base64.encodestring(
|
port = self.proxy_port
|
||||||
"{0}:{1}".format(self.proxy_user, self.proxy_password))
|
else:
|
||||||
headers = {'Proxy-Authorization': 'Basic {0}'.format(auth)}
|
host = target_host
|
||||||
connection.set_tunnel(proxy_host, int(proxy_port), headers)
|
port = target_port
|
||||||
|
|
||||||
return connection
|
if protocol == 'http':
|
||||||
|
connection = HTTPConnection(host, int(port))
|
||||||
def send_request_headers(self, connection, request_headers):
|
else:
|
||||||
if self.use_httplib:
|
connection = HTTPSConnection(
|
||||||
if self.proxy_host:
|
host, int(port), cert_file=self.cert_file)
|
||||||
for i in connection._buffer:
|
|
||||||
if i.startswith("Host: "):
|
if self.proxy_host:
|
||||||
connection._buffer.remove(i)
|
headers = None
|
||||||
connection.putheader(
|
if self.proxy_user and self.proxy_password:
|
||||||
'Host', "{0}:{1}".format(connection._tunnel_host,
|
auth = base64.encodestring(
|
||||||
connection._tunnel_port))
|
"{0}:{1}".format(self.proxy_user, self.proxy_password))
|
||||||
|
headers = {'Proxy-Authorization': 'Basic {0}'.format(auth)}
|
||||||
for name, value in request_headers:
|
connection.set_tunnel(proxy_host, int(proxy_port), headers)
|
||||||
if value:
|
|
||||||
connection.putheader(name, value)
|
return connection
|
||||||
|
|
||||||
connection.putheader('User-Agent', _USER_AGENT_STRING)
|
def send_request_headers(self, connection, request_headers):
|
||||||
connection.endheaders()
|
if self.use_httplib:
|
||||||
|
if self.proxy_host:
|
||||||
def send_request_body(self, connection, request_body):
|
for i in connection._buffer:
|
||||||
if request_body:
|
if i.startswith("Host: "):
|
||||||
assert isinstance(request_body, bytes)
|
connection._buffer.remove(i)
|
||||||
connection.send(request_body)
|
connection.putheader(
|
||||||
elif (not isinstance(connection, HTTPSConnection) and
|
'Host', "{0}:{1}".format(connection._tunnel_host,
|
||||||
not isinstance(connection, HTTPConnection)):
|
connection._tunnel_port))
|
||||||
connection.send(None)
|
|
||||||
|
for name, value in request_headers:
|
||||||
def perform_request(self, request):
|
if value:
|
||||||
''' Sends request to cloud service server and return the response. '''
|
connection.putheader(name, value)
|
||||||
connection = self.get_connection(request)
|
|
||||||
try:
|
connection.putheader('User-Agent', _USER_AGENT_STRING)
|
||||||
connection.putrequest(request.method, request.path)
|
connection.endheaders()
|
||||||
|
|
||||||
if not self.use_httplib:
|
def send_request_body(self, connection, request_body):
|
||||||
if self.proxy_host and self.proxy_user:
|
if request_body:
|
||||||
connection.set_proxy_credentials(
|
assert isinstance(request_body, bytes)
|
||||||
self.proxy_user, self.proxy_password)
|
connection.send(request_body)
|
||||||
|
elif (not isinstance(connection, HTTPSConnection) and
|
||||||
self.send_request_headers(connection, request.headers)
|
not isinstance(connection, HTTPConnection)):
|
||||||
self.send_request_body(connection, request.body)
|
connection.send(None)
|
||||||
|
|
||||||
resp = connection.getresponse()
|
def perform_request(self, request):
|
||||||
self.status = int(resp.status)
|
''' Sends request to cloud service server and return the response. '''
|
||||||
self.message = resp.reason
|
connection = self.get_connection(request)
|
||||||
self.respheader = headers = resp.getheaders()
|
try:
|
||||||
|
connection.putrequest(request.method, request.path)
|
||||||
# for consistency across platforms, make header names lowercase
|
|
||||||
for i, value in enumerate(headers):
|
if not self.use_httplib:
|
||||||
headers[i] = (value[0].lower(), value[1])
|
if self.proxy_host and self.proxy_user:
|
||||||
|
connection.set_proxy_credentials(
|
||||||
respbody = None
|
self.proxy_user, self.proxy_password)
|
||||||
if resp.length is None:
|
|
||||||
respbody = resp.read()
|
self.send_request_headers(connection, request.headers)
|
||||||
elif resp.length > 0:
|
self.send_request_body(connection, request.body)
|
||||||
respbody = resp.read(resp.length)
|
|
||||||
|
if DEBUG_REQUESTS and request.body:
|
||||||
response = HTTPResponse(
|
print('request:')
|
||||||
int(resp.status), resp.reason, headers, respbody)
|
try:
|
||||||
if self.status == 307:
|
print(request.body)
|
||||||
new_url = urlparse(dict(headers)['location'])
|
except:
|
||||||
request.host = new_url.hostname
|
pass
|
||||||
request.path = new_url.path
|
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
resp = connection.getresponse()
|
||||||
return self.perform_request(request)
|
self.status = int(resp.status)
|
||||||
if self.status >= 300:
|
self.message = resp.reason
|
||||||
raise HTTPError(self.status, self.message,
|
self.respheader = headers = resp.getheaders()
|
||||||
self.respheader, respbody)
|
|
||||||
|
# for consistency across platforms, make header names lowercase
|
||||||
return response
|
for i, value in enumerate(headers):
|
||||||
finally:
|
headers[i] = (value[0].lower(), value[1])
|
||||||
connection.close()
|
|
||||||
|
respbody = None
|
||||||
|
if resp.length is None:
|
||||||
|
respbody = resp.read()
|
||||||
|
elif resp.length > 0:
|
||||||
|
respbody = resp.read(resp.length)
|
||||||
|
|
||||||
|
if DEBUG_RESPONSES and respbody:
|
||||||
|
print('response:')
|
||||||
|
try:
|
||||||
|
print(respbody)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
response = HTTPResponse(
|
||||||
|
int(resp.status), resp.reason, headers, respbody)
|
||||||
|
if self.status == 307:
|
||||||
|
new_url = urlparse(dict(headers)['location'])
|
||||||
|
request.host = new_url.hostname
|
||||||
|
request.path = new_url.path
|
||||||
|
request.path, request.query = _update_request_uri_query(request)
|
||||||
|
return self.perform_request(request)
|
||||||
|
if self.status >= 300:
|
||||||
|
raise HTTPError(self.status, self.message,
|
||||||
|
self.respheader, respbody)
|
||||||
|
|
||||||
|
return response
|
||||||
|
finally:
|
||||||
|
connection.close()
|
||||||
|
|||||||
74
awx/lib/site-packages/azure/http/requestsclient.py
Normal file
74
awx/lib/site-packages/azure/http/requestsclient.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class _Response(object):
|
||||||
|
|
||||||
|
''' Response class corresponding to the response returned from httplib
|
||||||
|
HTTPConnection. '''
|
||||||
|
|
||||||
|
def __init__(self, response):
|
||||||
|
self.status = response.status_code
|
||||||
|
self.reason = response.reason
|
||||||
|
self.respbody = response.content
|
||||||
|
self.length = len(response.content)
|
||||||
|
self.headers = []
|
||||||
|
for key, name in response.headers.items():
|
||||||
|
self.headers.append((key.lower(), name))
|
||||||
|
|
||||||
|
def getheaders(self):
|
||||||
|
'''Returns response headers.'''
|
||||||
|
return self.headers
|
||||||
|
|
||||||
|
def read(self, _length):
|
||||||
|
'''Returns response body. '''
|
||||||
|
return self.respbody[:_length]
|
||||||
|
|
||||||
|
|
||||||
|
class _RequestsConnection(object):
|
||||||
|
|
||||||
|
def __init__(self, host, protocol, session):
|
||||||
|
self.host = host
|
||||||
|
self.protocol = protocol
|
||||||
|
self.session = session
|
||||||
|
self.headers = {}
|
||||||
|
self.method = None
|
||||||
|
self.body = None
|
||||||
|
self.response = None
|
||||||
|
self.uri = None
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_tunnel(self, host, port=None, headers=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_proxy_credentials(self, user, password):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def putrequest(self, method, uri):
|
||||||
|
self.method = method
|
||||||
|
self.uri = self.protocol + '://' + self.host + uri
|
||||||
|
|
||||||
|
def putheader(self, name, value):
|
||||||
|
self.headers[name] = value
|
||||||
|
|
||||||
|
def endheaders(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def send(self, request_body):
|
||||||
|
self.response = self.session.request(self.method, self.uri, data=request_body, headers=self.headers)
|
||||||
|
|
||||||
|
def getresponse(self):
|
||||||
|
return _Response(self.response)
|
||||||
@@ -1,471 +1,471 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
from ctypes import (
|
from ctypes import (
|
||||||
c_void_p,
|
c_void_p,
|
||||||
c_long,
|
c_long,
|
||||||
c_ulong,
|
c_ulong,
|
||||||
c_longlong,
|
c_longlong,
|
||||||
c_ulonglong,
|
c_ulonglong,
|
||||||
c_short,
|
c_short,
|
||||||
c_ushort,
|
c_ushort,
|
||||||
c_wchar_p,
|
c_wchar_p,
|
||||||
c_byte,
|
c_byte,
|
||||||
byref,
|
byref,
|
||||||
Structure,
|
Structure,
|
||||||
Union,
|
Union,
|
||||||
POINTER,
|
POINTER,
|
||||||
WINFUNCTYPE,
|
WINFUNCTYPE,
|
||||||
HRESULT,
|
HRESULT,
|
||||||
oledll,
|
oledll,
|
||||||
WinDLL,
|
WinDLL,
|
||||||
)
|
)
|
||||||
import ctypes
|
import ctypes
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.version_info >= (3,):
|
if sys.version_info >= (3,):
|
||||||
def unicode(text):
|
def unicode(text):
|
||||||
return text
|
return text
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Constants that are used in COM operations
|
# Constants that are used in COM operations
|
||||||
VT_EMPTY = 0
|
VT_EMPTY = 0
|
||||||
VT_NULL = 1
|
VT_NULL = 1
|
||||||
VT_I2 = 2
|
VT_I2 = 2
|
||||||
VT_I4 = 3
|
VT_I4 = 3
|
||||||
VT_BSTR = 8
|
VT_BSTR = 8
|
||||||
VT_BOOL = 11
|
VT_BOOL = 11
|
||||||
VT_I1 = 16
|
VT_I1 = 16
|
||||||
VT_UI1 = 17
|
VT_UI1 = 17
|
||||||
VT_UI2 = 18
|
VT_UI2 = 18
|
||||||
VT_UI4 = 19
|
VT_UI4 = 19
|
||||||
VT_I8 = 20
|
VT_I8 = 20
|
||||||
VT_UI8 = 21
|
VT_UI8 = 21
|
||||||
VT_ARRAY = 8192
|
VT_ARRAY = 8192
|
||||||
|
|
||||||
HTTPREQUEST_PROXYSETTING_PROXY = 2
|
HTTPREQUEST_PROXYSETTING_PROXY = 2
|
||||||
HTTPREQUEST_SETCREDENTIALS_FOR_PROXY = 1
|
HTTPREQUEST_SETCREDENTIALS_FOR_PROXY = 1
|
||||||
|
|
||||||
HTTPREQUEST_PROXY_SETTING = c_long
|
HTTPREQUEST_PROXY_SETTING = c_long
|
||||||
HTTPREQUEST_SETCREDENTIALS_FLAGS = c_long
|
HTTPREQUEST_SETCREDENTIALS_FLAGS = c_long
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Com related APIs that are used.
|
# Com related APIs that are used.
|
||||||
_ole32 = oledll.ole32
|
_ole32 = oledll.ole32
|
||||||
_oleaut32 = WinDLL('oleaut32')
|
_oleaut32 = WinDLL('oleaut32')
|
||||||
_CLSIDFromString = _ole32.CLSIDFromString
|
_CLSIDFromString = _ole32.CLSIDFromString
|
||||||
_CoInitialize = _ole32.CoInitialize
|
_CoInitialize = _ole32.CoInitialize
|
||||||
_CoInitialize.argtypes = [c_void_p]
|
_CoInitialize.argtypes = [c_void_p]
|
||||||
|
|
||||||
_CoCreateInstance = _ole32.CoCreateInstance
|
_CoCreateInstance = _ole32.CoCreateInstance
|
||||||
|
|
||||||
_SysAllocString = _oleaut32.SysAllocString
|
_SysAllocString = _oleaut32.SysAllocString
|
||||||
_SysAllocString.restype = c_void_p
|
_SysAllocString.restype = c_void_p
|
||||||
_SysAllocString.argtypes = [c_wchar_p]
|
_SysAllocString.argtypes = [c_wchar_p]
|
||||||
|
|
||||||
_SysFreeString = _oleaut32.SysFreeString
|
_SysFreeString = _oleaut32.SysFreeString
|
||||||
_SysFreeString.argtypes = [c_void_p]
|
_SysFreeString.argtypes = [c_void_p]
|
||||||
|
|
||||||
# SAFEARRAY*
|
# SAFEARRAY*
|
||||||
# SafeArrayCreateVector(_In_ VARTYPE vt,_In_ LONG lLbound,_In_ ULONG
|
# SafeArrayCreateVector(_In_ VARTYPE vt,_In_ LONG lLbound,_In_ ULONG
|
||||||
# cElements);
|
# cElements);
|
||||||
_SafeArrayCreateVector = _oleaut32.SafeArrayCreateVector
|
_SafeArrayCreateVector = _oleaut32.SafeArrayCreateVector
|
||||||
_SafeArrayCreateVector.restype = c_void_p
|
_SafeArrayCreateVector.restype = c_void_p
|
||||||
_SafeArrayCreateVector.argtypes = [c_ushort, c_long, c_ulong]
|
_SafeArrayCreateVector.argtypes = [c_ushort, c_long, c_ulong]
|
||||||
|
|
||||||
# HRESULT
|
# HRESULT
|
||||||
# SafeArrayAccessData(_In_ SAFEARRAY *psa, _Out_ void **ppvData);
|
# SafeArrayAccessData(_In_ SAFEARRAY *psa, _Out_ void **ppvData);
|
||||||
_SafeArrayAccessData = _oleaut32.SafeArrayAccessData
|
_SafeArrayAccessData = _oleaut32.SafeArrayAccessData
|
||||||
_SafeArrayAccessData.argtypes = [c_void_p, POINTER(c_void_p)]
|
_SafeArrayAccessData.argtypes = [c_void_p, POINTER(c_void_p)]
|
||||||
|
|
||||||
# HRESULT
|
# HRESULT
|
||||||
# SafeArrayUnaccessData(_In_ SAFEARRAY *psa);
|
# SafeArrayUnaccessData(_In_ SAFEARRAY *psa);
|
||||||
_SafeArrayUnaccessData = _oleaut32.SafeArrayUnaccessData
|
_SafeArrayUnaccessData = _oleaut32.SafeArrayUnaccessData
|
||||||
_SafeArrayUnaccessData.argtypes = [c_void_p]
|
_SafeArrayUnaccessData.argtypes = [c_void_p]
|
||||||
|
|
||||||
# HRESULT
|
# HRESULT
|
||||||
# SafeArrayGetUBound(_In_ SAFEARRAY *psa, _In_ UINT nDim, _Out_ LONG
|
# SafeArrayGetUBound(_In_ SAFEARRAY *psa, _In_ UINT nDim, _Out_ LONG
|
||||||
# *plUbound);
|
# *plUbound);
|
||||||
_SafeArrayGetUBound = _oleaut32.SafeArrayGetUBound
|
_SafeArrayGetUBound = _oleaut32.SafeArrayGetUBound
|
||||||
_SafeArrayGetUBound.argtypes = [c_void_p, c_ulong, POINTER(c_long)]
|
_SafeArrayGetUBound.argtypes = [c_void_p, c_ulong, POINTER(c_long)]
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
class BSTR(c_wchar_p):
|
class BSTR(c_wchar_p):
|
||||||
|
|
||||||
''' BSTR class in python. '''
|
''' BSTR class in python. '''
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
super(BSTR, self).__init__(_SysAllocString(value))
|
super(BSTR, self).__init__(_SysAllocString(value))
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
_SysFreeString(self)
|
_SysFreeString(self)
|
||||||
|
|
||||||
|
|
||||||
class VARIANT(Structure):
|
class VARIANT(Structure):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
VARIANT structure in python. Does not match the definition in
|
VARIANT structure in python. Does not match the definition in
|
||||||
MSDN exactly & it is only mapping the used fields. Field names are also
|
MSDN exactly & it is only mapping the used fields. Field names are also
|
||||||
slighty different.
|
slighty different.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
class _tagData(Union):
|
class _tagData(Union):
|
||||||
|
|
||||||
class _tagRecord(Structure):
|
class _tagRecord(Structure):
|
||||||
_fields_ = [('pvoid', c_void_p), ('precord', c_void_p)]
|
_fields_ = [('pvoid', c_void_p), ('precord', c_void_p)]
|
||||||
|
|
||||||
_fields_ = [('llval', c_longlong),
|
_fields_ = [('llval', c_longlong),
|
||||||
('ullval', c_ulonglong),
|
('ullval', c_ulonglong),
|
||||||
('lval', c_long),
|
('lval', c_long),
|
||||||
('ulval', c_ulong),
|
('ulval', c_ulong),
|
||||||
('ival', c_short),
|
('ival', c_short),
|
||||||
('boolval', c_ushort),
|
('boolval', c_ushort),
|
||||||
('bstrval', BSTR),
|
('bstrval', BSTR),
|
||||||
('parray', c_void_p),
|
('parray', c_void_p),
|
||||||
('record', _tagRecord)]
|
('record', _tagRecord)]
|
||||||
|
|
||||||
_fields_ = [('vt', c_ushort),
|
_fields_ = [('vt', c_ushort),
|
||||||
('wReserved1', c_ushort),
|
('wReserved1', c_ushort),
|
||||||
('wReserved2', c_ushort),
|
('wReserved2', c_ushort),
|
||||||
('wReserved3', c_ushort),
|
('wReserved3', c_ushort),
|
||||||
('vdata', _tagData)]
|
('vdata', _tagData)]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_empty():
|
def create_empty():
|
||||||
variant = VARIANT()
|
variant = VARIANT()
|
||||||
variant.vt = VT_EMPTY
|
variant.vt = VT_EMPTY
|
||||||
variant.vdata.llval = 0
|
variant.vdata.llval = 0
|
||||||
return variant
|
return variant
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_safearray_from_str(text):
|
def create_safearray_from_str(text):
|
||||||
variant = VARIANT()
|
variant = VARIANT()
|
||||||
variant.vt = VT_ARRAY | VT_UI1
|
variant.vt = VT_ARRAY | VT_UI1
|
||||||
|
|
||||||
length = len(text)
|
length = len(text)
|
||||||
variant.vdata.parray = _SafeArrayCreateVector(VT_UI1, 0, length)
|
variant.vdata.parray = _SafeArrayCreateVector(VT_UI1, 0, length)
|
||||||
pvdata = c_void_p()
|
pvdata = c_void_p()
|
||||||
_SafeArrayAccessData(variant.vdata.parray, byref(pvdata))
|
_SafeArrayAccessData(variant.vdata.parray, byref(pvdata))
|
||||||
ctypes.memmove(pvdata, text, length)
|
ctypes.memmove(pvdata, text, length)
|
||||||
_SafeArrayUnaccessData(variant.vdata.parray)
|
_SafeArrayUnaccessData(variant.vdata.parray)
|
||||||
|
|
||||||
return variant
|
return variant
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_bstr_from_str(text):
|
def create_bstr_from_str(text):
|
||||||
variant = VARIANT()
|
variant = VARIANT()
|
||||||
variant.vt = VT_BSTR
|
variant.vt = VT_BSTR
|
||||||
variant.vdata.bstrval = BSTR(text)
|
variant.vdata.bstrval = BSTR(text)
|
||||||
return variant
|
return variant
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_bool_false():
|
def create_bool_false():
|
||||||
variant = VARIANT()
|
variant = VARIANT()
|
||||||
variant.vt = VT_BOOL
|
variant.vt = VT_BOOL
|
||||||
variant.vdata.boolval = 0
|
variant.vdata.boolval = 0
|
||||||
return variant
|
return variant
|
||||||
|
|
||||||
def is_safearray_of_bytes(self):
|
def is_safearray_of_bytes(self):
|
||||||
return self.vt == VT_ARRAY | VT_UI1
|
return self.vt == VT_ARRAY | VT_UI1
|
||||||
|
|
||||||
def str_from_safearray(self):
|
def str_from_safearray(self):
|
||||||
assert self.vt == VT_ARRAY | VT_UI1
|
assert self.vt == VT_ARRAY | VT_UI1
|
||||||
pvdata = c_void_p()
|
pvdata = c_void_p()
|
||||||
count = c_long()
|
count = c_long()
|
||||||
_SafeArrayGetUBound(self.vdata.parray, 1, byref(count))
|
_SafeArrayGetUBound(self.vdata.parray, 1, byref(count))
|
||||||
count = c_long(count.value + 1)
|
count = c_long(count.value + 1)
|
||||||
_SafeArrayAccessData(self.vdata.parray, byref(pvdata))
|
_SafeArrayAccessData(self.vdata.parray, byref(pvdata))
|
||||||
text = ctypes.string_at(pvdata, count)
|
text = ctypes.string_at(pvdata, count)
|
||||||
_SafeArrayUnaccessData(self.vdata.parray)
|
_SafeArrayUnaccessData(self.vdata.parray)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
_VariantClear(self)
|
_VariantClear(self)
|
||||||
|
|
||||||
# HRESULT VariantClear(_Inout_ VARIANTARG *pvarg);
|
# HRESULT VariantClear(_Inout_ VARIANTARG *pvarg);
|
||||||
_VariantClear = _oleaut32.VariantClear
|
_VariantClear = _oleaut32.VariantClear
|
||||||
_VariantClear.argtypes = [POINTER(VARIANT)]
|
_VariantClear.argtypes = [POINTER(VARIANT)]
|
||||||
|
|
||||||
|
|
||||||
class GUID(Structure):
|
class GUID(Structure):
|
||||||
|
|
||||||
''' GUID structure in python. '''
|
''' GUID structure in python. '''
|
||||||
|
|
||||||
_fields_ = [("data1", c_ulong),
|
_fields_ = [("data1", c_ulong),
|
||||||
("data2", c_ushort),
|
("data2", c_ushort),
|
||||||
("data3", c_ushort),
|
("data3", c_ushort),
|
||||||
("data4", c_byte * 8)]
|
("data4", c_byte * 8)]
|
||||||
|
|
||||||
def __init__(self, name=None):
|
def __init__(self, name=None):
|
||||||
if name is not None:
|
if name is not None:
|
||||||
_CLSIDFromString(unicode(name), byref(self))
|
_CLSIDFromString(unicode(name), byref(self))
|
||||||
|
|
||||||
|
|
||||||
class _WinHttpRequest(c_void_p):
|
class _WinHttpRequest(c_void_p):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Maps the Com API to Python class functions. Not all methods in
|
Maps the Com API to Python class functions. Not all methods in
|
||||||
IWinHttpWebRequest are mapped - only the methods we use.
|
IWinHttpWebRequest are mapped - only the methods we use.
|
||||||
'''
|
'''
|
||||||
_AddRef = WINFUNCTYPE(c_long) \
|
_AddRef = WINFUNCTYPE(c_long) \
|
||||||
(1, 'AddRef')
|
(1, 'AddRef')
|
||||||
_Release = WINFUNCTYPE(c_long) \
|
_Release = WINFUNCTYPE(c_long) \
|
||||||
(2, 'Release')
|
(2, 'Release')
|
||||||
_SetProxy = WINFUNCTYPE(HRESULT,
|
_SetProxy = WINFUNCTYPE(HRESULT,
|
||||||
HTTPREQUEST_PROXY_SETTING,
|
HTTPREQUEST_PROXY_SETTING,
|
||||||
VARIANT,
|
VARIANT,
|
||||||
VARIANT) \
|
VARIANT) \
|
||||||
(7, 'SetProxy')
|
(7, 'SetProxy')
|
||||||
_SetCredentials = WINFUNCTYPE(HRESULT,
|
_SetCredentials = WINFUNCTYPE(HRESULT,
|
||||||
BSTR,
|
BSTR,
|
||||||
BSTR,
|
BSTR,
|
||||||
HTTPREQUEST_SETCREDENTIALS_FLAGS) \
|
HTTPREQUEST_SETCREDENTIALS_FLAGS) \
|
||||||
(8, 'SetCredentials')
|
(8, 'SetCredentials')
|
||||||
_Open = WINFUNCTYPE(HRESULT, BSTR, BSTR, VARIANT) \
|
_Open = WINFUNCTYPE(HRESULT, BSTR, BSTR, VARIANT) \
|
||||||
(9, 'Open')
|
(9, 'Open')
|
||||||
_SetRequestHeader = WINFUNCTYPE(HRESULT, BSTR, BSTR) \
|
_SetRequestHeader = WINFUNCTYPE(HRESULT, BSTR, BSTR) \
|
||||||
(10, 'SetRequestHeader')
|
(10, 'SetRequestHeader')
|
||||||
_GetResponseHeader = WINFUNCTYPE(HRESULT, BSTR, POINTER(c_void_p)) \
|
_GetResponseHeader = WINFUNCTYPE(HRESULT, BSTR, POINTER(c_void_p)) \
|
||||||
(11, 'GetResponseHeader')
|
(11, 'GetResponseHeader')
|
||||||
_GetAllResponseHeaders = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \
|
_GetAllResponseHeaders = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \
|
||||||
(12, 'GetAllResponseHeaders')
|
(12, 'GetAllResponseHeaders')
|
||||||
_Send = WINFUNCTYPE(HRESULT, VARIANT) \
|
_Send = WINFUNCTYPE(HRESULT, VARIANT) \
|
||||||
(13, 'Send')
|
(13, 'Send')
|
||||||
_Status = WINFUNCTYPE(HRESULT, POINTER(c_long)) \
|
_Status = WINFUNCTYPE(HRESULT, POINTER(c_long)) \
|
||||||
(14, 'Status')
|
(14, 'Status')
|
||||||
_StatusText = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \
|
_StatusText = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \
|
||||||
(15, 'StatusText')
|
(15, 'StatusText')
|
||||||
_ResponseText = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \
|
_ResponseText = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \
|
||||||
(16, 'ResponseText')
|
(16, 'ResponseText')
|
||||||
_ResponseBody = WINFUNCTYPE(HRESULT, POINTER(VARIANT)) \
|
_ResponseBody = WINFUNCTYPE(HRESULT, POINTER(VARIANT)) \
|
||||||
(17, 'ResponseBody')
|
(17, 'ResponseBody')
|
||||||
_ResponseStream = WINFUNCTYPE(HRESULT, POINTER(VARIANT)) \
|
_ResponseStream = WINFUNCTYPE(HRESULT, POINTER(VARIANT)) \
|
||||||
(18, 'ResponseStream')
|
(18, 'ResponseStream')
|
||||||
_WaitForResponse = WINFUNCTYPE(HRESULT, VARIANT, POINTER(c_ushort)) \
|
_WaitForResponse = WINFUNCTYPE(HRESULT, VARIANT, POINTER(c_ushort)) \
|
||||||
(21, 'WaitForResponse')
|
(21, 'WaitForResponse')
|
||||||
_Abort = WINFUNCTYPE(HRESULT) \
|
_Abort = WINFUNCTYPE(HRESULT) \
|
||||||
(22, 'Abort')
|
(22, 'Abort')
|
||||||
_SetTimeouts = WINFUNCTYPE(HRESULT, c_long, c_long, c_long, c_long) \
|
_SetTimeouts = WINFUNCTYPE(HRESULT, c_long, c_long, c_long, c_long) \
|
||||||
(23, 'SetTimeouts')
|
(23, 'SetTimeouts')
|
||||||
_SetClientCertificate = WINFUNCTYPE(HRESULT, BSTR) \
|
_SetClientCertificate = WINFUNCTYPE(HRESULT, BSTR) \
|
||||||
(24, 'SetClientCertificate')
|
(24, 'SetClientCertificate')
|
||||||
|
|
||||||
def open(self, method, url):
|
def open(self, method, url):
|
||||||
'''
|
'''
|
||||||
Opens the request.
|
Opens the request.
|
||||||
|
|
||||||
method: the request VERB 'GET', 'POST', etc.
|
method: the request VERB 'GET', 'POST', etc.
|
||||||
url: the url to connect
|
url: the url to connect
|
||||||
'''
|
'''
|
||||||
_WinHttpRequest._SetTimeouts(self, 0, 65000, 65000, 65000)
|
_WinHttpRequest._SetTimeouts(self, 0, 65000, 65000, 65000)
|
||||||
|
|
||||||
flag = VARIANT.create_bool_false()
|
flag = VARIANT.create_bool_false()
|
||||||
_method = BSTR(method)
|
_method = BSTR(method)
|
||||||
_url = BSTR(url)
|
_url = BSTR(url)
|
||||||
_WinHttpRequest._Open(self, _method, _url, flag)
|
_WinHttpRequest._Open(self, _method, _url, flag)
|
||||||
|
|
||||||
def set_request_header(self, name, value):
|
def set_request_header(self, name, value):
|
||||||
''' Sets the request header. '''
|
''' Sets the request header. '''
|
||||||
|
|
||||||
_name = BSTR(name)
|
_name = BSTR(name)
|
||||||
_value = BSTR(value)
|
_value = BSTR(value)
|
||||||
_WinHttpRequest._SetRequestHeader(self, _name, _value)
|
_WinHttpRequest._SetRequestHeader(self, _name, _value)
|
||||||
|
|
||||||
def get_all_response_headers(self):
|
def get_all_response_headers(self):
|
||||||
''' Gets back all response headers. '''
|
''' Gets back all response headers. '''
|
||||||
|
|
||||||
bstr_headers = c_void_p()
|
bstr_headers = c_void_p()
|
||||||
_WinHttpRequest._GetAllResponseHeaders(self, byref(bstr_headers))
|
_WinHttpRequest._GetAllResponseHeaders(self, byref(bstr_headers))
|
||||||
bstr_headers = ctypes.cast(bstr_headers, c_wchar_p)
|
bstr_headers = ctypes.cast(bstr_headers, c_wchar_p)
|
||||||
headers = bstr_headers.value
|
headers = bstr_headers.value
|
||||||
_SysFreeString(bstr_headers)
|
_SysFreeString(bstr_headers)
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
def send(self, request=None):
|
def send(self, request=None):
|
||||||
''' Sends the request body. '''
|
''' Sends the request body. '''
|
||||||
|
|
||||||
# Sends VT_EMPTY if it is GET, HEAD request.
|
# Sends VT_EMPTY if it is GET, HEAD request.
|
||||||
if request is None:
|
if request is None:
|
||||||
var_empty = VARIANT.create_empty()
|
var_empty = VARIANT.create_empty()
|
||||||
_WinHttpRequest._Send(self, var_empty)
|
_WinHttpRequest._Send(self, var_empty)
|
||||||
else: # Sends request body as SAFEArray.
|
else: # Sends request body as SAFEArray.
|
||||||
_request = VARIANT.create_safearray_from_str(request)
|
_request = VARIANT.create_safearray_from_str(request)
|
||||||
_WinHttpRequest._Send(self, _request)
|
_WinHttpRequest._Send(self, _request)
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
''' Gets status of response. '''
|
''' Gets status of response. '''
|
||||||
|
|
||||||
status = c_long()
|
status = c_long()
|
||||||
_WinHttpRequest._Status(self, byref(status))
|
_WinHttpRequest._Status(self, byref(status))
|
||||||
return int(status.value)
|
return int(status.value)
|
||||||
|
|
||||||
def status_text(self):
|
def status_text(self):
|
||||||
''' Gets status text of response. '''
|
''' Gets status text of response. '''
|
||||||
|
|
||||||
bstr_status_text = c_void_p()
|
bstr_status_text = c_void_p()
|
||||||
_WinHttpRequest._StatusText(self, byref(bstr_status_text))
|
_WinHttpRequest._StatusText(self, byref(bstr_status_text))
|
||||||
bstr_status_text = ctypes.cast(bstr_status_text, c_wchar_p)
|
bstr_status_text = ctypes.cast(bstr_status_text, c_wchar_p)
|
||||||
status_text = bstr_status_text.value
|
status_text = bstr_status_text.value
|
||||||
_SysFreeString(bstr_status_text)
|
_SysFreeString(bstr_status_text)
|
||||||
return status_text
|
return status_text
|
||||||
|
|
||||||
def response_body(self):
|
def response_body(self):
|
||||||
'''
|
'''
|
||||||
Gets response body as a SAFEARRAY and converts the SAFEARRAY to str.
|
Gets response body as a SAFEARRAY and converts the SAFEARRAY to str.
|
||||||
If it is an xml file, it always contains 3 characters before <?xml,
|
If it is an xml file, it always contains 3 characters before <?xml,
|
||||||
so we remove them.
|
so we remove them.
|
||||||
'''
|
'''
|
||||||
var_respbody = VARIANT()
|
var_respbody = VARIANT()
|
||||||
_WinHttpRequest._ResponseBody(self, byref(var_respbody))
|
_WinHttpRequest._ResponseBody(self, byref(var_respbody))
|
||||||
if var_respbody.is_safearray_of_bytes():
|
if var_respbody.is_safearray_of_bytes():
|
||||||
respbody = var_respbody.str_from_safearray()
|
respbody = var_respbody.str_from_safearray()
|
||||||
if respbody[3:].startswith(b'<?xml') and\
|
if respbody[3:].startswith(b'<?xml') and\
|
||||||
respbody.startswith(b'\xef\xbb\xbf'):
|
respbody.startswith(b'\xef\xbb\xbf'):
|
||||||
respbody = respbody[3:]
|
respbody = respbody[3:]
|
||||||
return respbody
|
return respbody
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def set_client_certificate(self, certificate):
|
def set_client_certificate(self, certificate):
|
||||||
'''Sets client certificate for the request. '''
|
'''Sets client certificate for the request. '''
|
||||||
_certificate = BSTR(certificate)
|
_certificate = BSTR(certificate)
|
||||||
_WinHttpRequest._SetClientCertificate(self, _certificate)
|
_WinHttpRequest._SetClientCertificate(self, _certificate)
|
||||||
|
|
||||||
def set_tunnel(self, host, port):
|
def set_tunnel(self, host, port):
|
||||||
''' Sets up the host and the port for the HTTP CONNECT Tunnelling.'''
|
''' Sets up the host and the port for the HTTP CONNECT Tunnelling.'''
|
||||||
url = host
|
url = host
|
||||||
if port:
|
if port:
|
||||||
url = url + u':' + port
|
url = url + u':' + port
|
||||||
|
|
||||||
var_host = VARIANT.create_bstr_from_str(url)
|
var_host = VARIANT.create_bstr_from_str(url)
|
||||||
var_empty = VARIANT.create_empty()
|
var_empty = VARIANT.create_empty()
|
||||||
|
|
||||||
_WinHttpRequest._SetProxy(
|
_WinHttpRequest._SetProxy(
|
||||||
self, HTTPREQUEST_PROXYSETTING_PROXY, var_host, var_empty)
|
self, HTTPREQUEST_PROXYSETTING_PROXY, var_host, var_empty)
|
||||||
|
|
||||||
def set_proxy_credentials(self, user, password):
|
def set_proxy_credentials(self, user, password):
|
||||||
_WinHttpRequest._SetCredentials(
|
_WinHttpRequest._SetCredentials(
|
||||||
self, BSTR(user), BSTR(password),
|
self, BSTR(user), BSTR(password),
|
||||||
HTTPREQUEST_SETCREDENTIALS_FOR_PROXY)
|
HTTPREQUEST_SETCREDENTIALS_FOR_PROXY)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self.value is not None:
|
if self.value is not None:
|
||||||
_WinHttpRequest._Release(self)
|
_WinHttpRequest._Release(self)
|
||||||
|
|
||||||
|
|
||||||
class _Response(object):
|
class _Response(object):
|
||||||
|
|
||||||
''' Response class corresponding to the response returned from httplib
|
''' Response class corresponding to the response returned from httplib
|
||||||
HTTPConnection. '''
|
HTTPConnection. '''
|
||||||
|
|
||||||
def __init__(self, _status, _status_text, _length, _headers, _respbody):
|
def __init__(self, _status, _status_text, _length, _headers, _respbody):
|
||||||
self.status = _status
|
self.status = _status
|
||||||
self.reason = _status_text
|
self.reason = _status_text
|
||||||
self.length = _length
|
self.length = _length
|
||||||
self.headers = _headers
|
self.headers = _headers
|
||||||
self.respbody = _respbody
|
self.respbody = _respbody
|
||||||
|
|
||||||
def getheaders(self):
|
def getheaders(self):
|
||||||
'''Returns response headers.'''
|
'''Returns response headers.'''
|
||||||
return self.headers
|
return self.headers
|
||||||
|
|
||||||
def read(self, _length):
|
def read(self, _length):
|
||||||
'''Returns resonse body. '''
|
'''Returns resonse body. '''
|
||||||
return self.respbody[:_length]
|
return self.respbody[:_length]
|
||||||
|
|
||||||
|
|
||||||
class _HTTPConnection(object):
|
class _HTTPConnection(object):
|
||||||
|
|
||||||
''' Class corresponding to httplib HTTPConnection class. '''
|
''' Class corresponding to httplib HTTPConnection class. '''
|
||||||
|
|
||||||
def __init__(self, host, cert_file=None, key_file=None, protocol='http'):
|
def __init__(self, host, cert_file=None, key_file=None, protocol='http'):
|
||||||
''' initialize the IWinHttpWebRequest Com Object.'''
|
''' initialize the IWinHttpWebRequest Com Object.'''
|
||||||
self.host = unicode(host)
|
self.host = unicode(host)
|
||||||
self.cert_file = cert_file
|
self.cert_file = cert_file
|
||||||
self._httprequest = _WinHttpRequest()
|
self._httprequest = _WinHttpRequest()
|
||||||
self.protocol = protocol
|
self.protocol = protocol
|
||||||
clsid = GUID('{2087C2F4-2CEF-4953-A8AB-66779B670495}')
|
clsid = GUID('{2087C2F4-2CEF-4953-A8AB-66779B670495}')
|
||||||
iid = GUID('{016FE2EC-B2C8-45F8-B23B-39E53A75396B}')
|
iid = GUID('{016FE2EC-B2C8-45F8-B23B-39E53A75396B}')
|
||||||
_CoInitialize(None)
|
_CoInitialize(None)
|
||||||
_CoCreateInstance(byref(clsid), 0, 1, byref(iid),
|
_CoCreateInstance(byref(clsid), 0, 1, byref(iid),
|
||||||
byref(self._httprequest))
|
byref(self._httprequest))
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_tunnel(self, host, port=None, headers=None):
|
def set_tunnel(self, host, port=None, headers=None):
|
||||||
''' Sets up the host and the port for the HTTP CONNECT Tunnelling. '''
|
''' Sets up the host and the port for the HTTP CONNECT Tunnelling. '''
|
||||||
self._httprequest.set_tunnel(unicode(host), unicode(str(port)))
|
self._httprequest.set_tunnel(unicode(host), unicode(str(port)))
|
||||||
|
|
||||||
def set_proxy_credentials(self, user, password):
|
def set_proxy_credentials(self, user, password):
|
||||||
self._httprequest.set_proxy_credentials(
|
self._httprequest.set_proxy_credentials(
|
||||||
unicode(user), unicode(password))
|
unicode(user), unicode(password))
|
||||||
|
|
||||||
def putrequest(self, method, uri):
|
def putrequest(self, method, uri):
|
||||||
''' Connects to host and sends the request. '''
|
''' Connects to host and sends the request. '''
|
||||||
|
|
||||||
protocol = unicode(self.protocol + '://')
|
protocol = unicode(self.protocol + '://')
|
||||||
url = protocol + self.host + unicode(uri)
|
url = protocol + self.host + unicode(uri)
|
||||||
self._httprequest.open(unicode(method), url)
|
self._httprequest.open(unicode(method), url)
|
||||||
|
|
||||||
# sets certificate for the connection if cert_file is set.
|
# sets certificate for the connection if cert_file is set.
|
||||||
if self.cert_file is not None:
|
if self.cert_file is not None:
|
||||||
self._httprequest.set_client_certificate(unicode(self.cert_file))
|
self._httprequest.set_client_certificate(unicode(self.cert_file))
|
||||||
|
|
||||||
def putheader(self, name, value):
|
def putheader(self, name, value):
|
||||||
''' Sends the headers of request. '''
|
''' Sends the headers of request. '''
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
name = str(name).decode('utf-8')
|
name = str(name).decode('utf-8')
|
||||||
value = str(value).decode('utf-8')
|
value = str(value).decode('utf-8')
|
||||||
self._httprequest.set_request_header(name, value)
|
self._httprequest.set_request_header(name, value)
|
||||||
|
|
||||||
def endheaders(self):
|
def endheaders(self):
|
||||||
''' No operation. Exists only to provide the same interface of httplib
|
''' No operation. Exists only to provide the same interface of httplib
|
||||||
HTTPConnection.'''
|
HTTPConnection.'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def send(self, request_body):
|
def send(self, request_body):
|
||||||
''' Sends request body. '''
|
''' Sends request body. '''
|
||||||
if not request_body:
|
if not request_body:
|
||||||
self._httprequest.send()
|
self._httprequest.send()
|
||||||
else:
|
else:
|
||||||
self._httprequest.send(request_body)
|
self._httprequest.send(request_body)
|
||||||
|
|
||||||
def getresponse(self):
|
def getresponse(self):
|
||||||
''' Gets the response and generates the _Response object'''
|
''' Gets the response and generates the _Response object'''
|
||||||
status = self._httprequest.status()
|
status = self._httprequest.status()
|
||||||
status_text = self._httprequest.status_text()
|
status_text = self._httprequest.status_text()
|
||||||
|
|
||||||
resp_headers = self._httprequest.get_all_response_headers()
|
resp_headers = self._httprequest.get_all_response_headers()
|
||||||
fixed_headers = []
|
fixed_headers = []
|
||||||
for resp_header in resp_headers.split('\n'):
|
for resp_header in resp_headers.split('\n'):
|
||||||
if (resp_header.startswith('\t') or\
|
if (resp_header.startswith('\t') or\
|
||||||
resp_header.startswith(' ')) and fixed_headers:
|
resp_header.startswith(' ')) and fixed_headers:
|
||||||
# append to previous header
|
# append to previous header
|
||||||
fixed_headers[-1] += resp_header
|
fixed_headers[-1] += resp_header
|
||||||
else:
|
else:
|
||||||
fixed_headers.append(resp_header)
|
fixed_headers.append(resp_header)
|
||||||
|
|
||||||
headers = []
|
headers = []
|
||||||
for resp_header in fixed_headers:
|
for resp_header in fixed_headers:
|
||||||
if ':' in resp_header:
|
if ':' in resp_header:
|
||||||
pos = resp_header.find(':')
|
pos = resp_header.find(':')
|
||||||
headers.append(
|
headers.append(
|
||||||
(resp_header[:pos].lower(), resp_header[pos + 1:].strip()))
|
(resp_header[:pos].lower(), resp_header[pos + 1:].strip()))
|
||||||
|
|
||||||
body = self._httprequest.response_body()
|
body = self._httprequest.response_body()
|
||||||
length = len(body)
|
length = len(body)
|
||||||
|
|
||||||
return _Response(status, status_text, length, headers, body)
|
return _Response(status, status_text, length, headers, body)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
|||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
from azure import (
|
||||||
|
MANAGEMENT_HOST,
|
||||||
|
_str
|
||||||
|
)
|
||||||
|
from azure.servicemanagement import (
|
||||||
|
CloudServices,
|
||||||
|
)
|
||||||
|
from azure.servicemanagement.servicemanagementclient import (
|
||||||
|
_ServiceManagementClient,
|
||||||
|
)
|
||||||
|
|
||||||
|
class SchedulerManagementService(_ServiceManagementClient):
|
||||||
|
''' Note that this class is a preliminary work on Scheduler
|
||||||
|
management. Since it lack a lot a features, final version
|
||||||
|
can be slightly different from the current one.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, subscription_id=None, cert_file=None,
|
||||||
|
host=MANAGEMENT_HOST, request_session=None):
|
||||||
|
'''
|
||||||
|
Initializes the scheduler management service.
|
||||||
|
|
||||||
|
subscription_id: Subscription to manage.
|
||||||
|
cert_file:
|
||||||
|
Path to .pem certificate file (httplib), or location of the
|
||||||
|
certificate in your Personal certificate store (winhttp) in the
|
||||||
|
CURRENT_USER\my\CertificateName format.
|
||||||
|
If a request_session is specified, then this is unused.
|
||||||
|
host: Live ServiceClient URL. Defaults to Azure public cloud.
|
||||||
|
request_session:
|
||||||
|
Session object to use for http requests. If this is specified, it
|
||||||
|
replaces the default use of httplib or winhttp. Also, the cert_file
|
||||||
|
parameter is unused when a session is passed in.
|
||||||
|
The session object handles authentication, and as such can support
|
||||||
|
multiple types of authentication: .pem certificate, oauth.
|
||||||
|
For example, you can pass in a Session instance from the requests
|
||||||
|
library. To use .pem certificate authentication with requests
|
||||||
|
library, set the path to the .pem file on the session.cert
|
||||||
|
attribute.
|
||||||
|
'''
|
||||||
|
super(SchedulerManagementService, self).__init__(
|
||||||
|
subscription_id, cert_file, host, request_session)
|
||||||
|
|
||||||
|
#--Operations for scheduler ----------------------------------------
|
||||||
|
def list_cloud_services(self):
|
||||||
|
'''
|
||||||
|
List the cloud services for scheduling defined on the account.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_list_cloud_services_path(),
|
||||||
|
CloudServices)
|
||||||
|
|
||||||
|
|
||||||
|
#--Helper functions --------------------------------------------------
|
||||||
|
def _get_list_cloud_services_path(self):
|
||||||
|
return self._get_path('cloudservices', None)
|
||||||
|
|
||||||
@@ -1,113 +1,534 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
from azure import (
|
from azure import (
|
||||||
MANAGEMENT_HOST,
|
MANAGEMENT_HOST,
|
||||||
_convert_response_to_feeds,
|
_convert_response_to_feeds,
|
||||||
_str,
|
_str,
|
||||||
_validate_not_none,
|
_validate_not_none,
|
||||||
)
|
_convert_xml_to_windows_azure_object,
|
||||||
from azure.servicemanagement import (
|
)
|
||||||
_ServiceBusManagementXmlSerializer,
|
from azure.servicemanagement import (
|
||||||
)
|
_ServiceBusManagementXmlSerializer,
|
||||||
from azure.servicemanagement.servicemanagementclient import (
|
QueueDescription,
|
||||||
_ServiceManagementClient,
|
TopicDescription,
|
||||||
)
|
NotificationHubDescription,
|
||||||
|
RelayDescription,
|
||||||
|
MetricProperties,
|
||||||
class ServiceBusManagementService(_ServiceManagementClient):
|
MetricValues,
|
||||||
|
MetricRollups,
|
||||||
def __init__(self, subscription_id=None, cert_file=None,
|
)
|
||||||
host=MANAGEMENT_HOST):
|
from azure.servicemanagement.servicemanagementclient import (
|
||||||
super(ServiceBusManagementService, self).__init__(
|
_ServiceManagementClient,
|
||||||
subscription_id, cert_file, host)
|
)
|
||||||
|
|
||||||
#--Operations for service bus ----------------------------------------
|
from functools import partial
|
||||||
def get_regions(self):
|
|
||||||
'''
|
X_MS_VERSION = '2012-03-01'
|
||||||
Get list of available service bus regions.
|
|
||||||
'''
|
class ServiceBusManagementService(_ServiceManagementClient):
|
||||||
response = self._perform_get(
|
|
||||||
self._get_path('services/serviceBus/Regions/', None),
|
def __init__(self, subscription_id=None, cert_file=None,
|
||||||
None)
|
host=MANAGEMENT_HOST, request_session=None):
|
||||||
|
'''
|
||||||
return _convert_response_to_feeds(
|
Initializes the service bus management service.
|
||||||
response,
|
|
||||||
_ServiceBusManagementXmlSerializer.xml_to_region)
|
subscription_id: Subscription to manage.
|
||||||
|
cert_file:
|
||||||
def list_namespaces(self):
|
Path to .pem certificate file (httplib), or location of the
|
||||||
'''
|
certificate in your Personal certificate store (winhttp) in the
|
||||||
List the service bus namespaces defined on the account.
|
CURRENT_USER\my\CertificateName format.
|
||||||
'''
|
If a request_session is specified, then this is unused.
|
||||||
response = self._perform_get(
|
host: Live ServiceClient URL. Defaults to Azure public cloud.
|
||||||
self._get_path('services/serviceBus/Namespaces/', None),
|
request_session:
|
||||||
None)
|
Session object to use for http requests. If this is specified, it
|
||||||
|
replaces the default use of httplib or winhttp. Also, the cert_file
|
||||||
return _convert_response_to_feeds(
|
parameter is unused when a session is passed in.
|
||||||
response,
|
The session object handles authentication, and as such can support
|
||||||
_ServiceBusManagementXmlSerializer.xml_to_namespace)
|
multiple types of authentication: .pem certificate, oauth.
|
||||||
|
For example, you can pass in a Session instance from the requests
|
||||||
def get_namespace(self, name):
|
library. To use .pem certificate authentication with requests
|
||||||
'''
|
library, set the path to the .pem file on the session.cert
|
||||||
Get details about a specific namespace.
|
attribute.
|
||||||
|
'''
|
||||||
name: Name of the service bus namespace.
|
super(ServiceBusManagementService, self).__init__(
|
||||||
'''
|
subscription_id, cert_file, host, request_session)
|
||||||
response = self._perform_get(
|
self.x_ms_version = X_MS_VERSION
|
||||||
self._get_path('services/serviceBus/Namespaces', name),
|
|
||||||
None)
|
# Operations for service bus ----------------------------------------
|
||||||
|
def get_regions(self):
|
||||||
return _ServiceBusManagementXmlSerializer.xml_to_namespace(
|
'''
|
||||||
response.body)
|
Get list of available service bus regions.
|
||||||
|
'''
|
||||||
def create_namespace(self, name, region):
|
response = self._perform_get(
|
||||||
'''
|
self._get_path('services/serviceBus/Regions/', None),
|
||||||
Create a new service bus namespace.
|
None)
|
||||||
|
|
||||||
name: Name of the service bus namespace to create.
|
return _convert_response_to_feeds(
|
||||||
region: Region to create the namespace in.
|
response,
|
||||||
'''
|
_ServiceBusManagementXmlSerializer.xml_to_region)
|
||||||
_validate_not_none('name', name)
|
|
||||||
|
def list_namespaces(self):
|
||||||
return self._perform_put(
|
'''
|
||||||
self._get_path('services/serviceBus/Namespaces', name),
|
List the service bus namespaces defined on the account.
|
||||||
_ServiceBusManagementXmlSerializer.namespace_to_xml(region))
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
def delete_namespace(self, name):
|
self._get_path('services/serviceBus/Namespaces/', None),
|
||||||
'''
|
None)
|
||||||
Delete a service bus namespace.
|
|
||||||
|
return _convert_response_to_feeds(
|
||||||
name: Name of the service bus namespace to delete.
|
response,
|
||||||
'''
|
_ServiceBusManagementXmlSerializer.xml_to_namespace)
|
||||||
_validate_not_none('name', name)
|
|
||||||
|
def get_namespace(self, name):
|
||||||
return self._perform_delete(
|
'''
|
||||||
self._get_path('services/serviceBus/Namespaces', name),
|
Get details about a specific namespace.
|
||||||
None)
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
def check_namespace_availability(self, name):
|
'''
|
||||||
'''
|
response = self._perform_get(
|
||||||
Checks to see if the specified service bus namespace is available, or
|
self._get_path('services/serviceBus/Namespaces', name),
|
||||||
if it has already been taken.
|
None)
|
||||||
|
|
||||||
name: Name of the service bus namespace to validate.
|
return _ServiceBusManagementXmlSerializer.xml_to_namespace(
|
||||||
'''
|
response.body)
|
||||||
_validate_not_none('name', name)
|
|
||||||
|
def create_namespace(self, name, region):
|
||||||
response = self._perform_get(
|
'''
|
||||||
self._get_path('services/serviceBus/CheckNamespaceAvailability',
|
Create a new service bus namespace.
|
||||||
None) + '/?namespace=' + _str(name), None)
|
|
||||||
|
name: Name of the service bus namespace to create.
|
||||||
return _ServiceBusManagementXmlSerializer.xml_to_namespace_availability(
|
region: Region to create the namespace in.
|
||||||
response.body)
|
'''
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
|
||||||
|
return self._perform_put(
|
||||||
|
self._get_path('services/serviceBus/Namespaces', name),
|
||||||
|
_ServiceBusManagementXmlSerializer.namespace_to_xml(region))
|
||||||
|
|
||||||
|
def delete_namespace(self, name):
|
||||||
|
'''
|
||||||
|
Delete a service bus namespace.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace to delete.
|
||||||
|
'''
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
|
||||||
|
return self._perform_delete(
|
||||||
|
self._get_path('services/serviceBus/Namespaces', name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
def check_namespace_availability(self, name):
|
||||||
|
'''
|
||||||
|
Checks to see if the specified service bus namespace is available, or
|
||||||
|
if it has already been taken.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace to validate.
|
||||||
|
'''
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_path('services/serviceBus/CheckNamespaceAvailability',
|
||||||
|
None) + '/?namespace=' + _str(name), None)
|
||||||
|
|
||||||
|
return _ServiceBusManagementXmlSerializer.xml_to_namespace_availability(
|
||||||
|
response.body)
|
||||||
|
|
||||||
|
def list_queues(self, name):
|
||||||
|
'''
|
||||||
|
Enumerates the queues in the service namespace.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
'''
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_list_queues_path(name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_convert_xml_to_windows_azure_object,
|
||||||
|
azure_type=QueueDescription))
|
||||||
|
|
||||||
|
def list_topics(self, name):
|
||||||
|
'''
|
||||||
|
Retrieves the topics in the service namespace.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_list_topics_path(name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_convert_xml_to_windows_azure_object,
|
||||||
|
azure_type=TopicDescription))
|
||||||
|
|
||||||
|
def list_notification_hubs(self, name):
|
||||||
|
'''
|
||||||
|
Retrieves the notification hubs in the service namespace.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_list_notification_hubs_path(name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_convert_xml_to_windows_azure_object,
|
||||||
|
azure_type=NotificationHubDescription))
|
||||||
|
|
||||||
|
def list_relays(self, name):
|
||||||
|
'''
|
||||||
|
Retrieves the relays in the service namespace.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_list_relays_path(name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_convert_xml_to_windows_azure_object,
|
||||||
|
azure_type=RelayDescription))
|
||||||
|
|
||||||
|
def get_supported_metrics_queue(self, name, queue_name):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and queue
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
queue_name: Name of the service bus queue in this namespace.
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_supported_metrics_queue_path(name, queue_name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricProperties))
|
||||||
|
|
||||||
|
def get_supported_metrics_topic(self, name, topic_name):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and topic
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
topic_name: Name of the service bus queue in this namespace.
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_supported_metrics_topic_path(name, topic_name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricProperties))
|
||||||
|
|
||||||
|
def get_supported_metrics_notification_hub(self, name, hub_name):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and topic
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
hub_name: Name of the service bus notification hub in this namespace.
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_supported_metrics_hub_path(name, hub_name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricProperties))
|
||||||
|
|
||||||
|
def get_supported_metrics_relay(self, name, relay_name):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and relay
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
relay_name: Name of the service bus relay in this namespace.
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_supported_metrics_relay_path(name, relay_name),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricProperties))
|
||||||
|
|
||||||
|
def get_metrics_data_queue(self, name, queue_name, metric, rollup, filter_expresssion):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and queue
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
queue_name: Name of the service bus queue in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
rollup: name of a supported rollup
|
||||||
|
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_data_queue_path(name, queue_name, metric, rollup, filter_expresssion),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricValues))
|
||||||
|
|
||||||
|
def get_metrics_data_topic(self, name, topic_name, metric, rollup, filter_expresssion):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and topic
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
topic_name: Name of the service bus queue in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
rollup: name of a supported rollup
|
||||||
|
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_data_topic_path(name, topic_name, metric, rollup, filter_expresssion),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricValues))
|
||||||
|
|
||||||
|
def get_metrics_data_notification_hub(self, name, hub_name, metric, rollup, filter_expresssion):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and topic
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
hub_name: Name of the service bus notification hub in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
rollup: name of a supported rollup
|
||||||
|
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_data_hub_path(name, hub_name, metric, rollup, filter_expresssion),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricValues))
|
||||||
|
|
||||||
|
def get_metrics_data_relay(self, name, relay_name, metric, rollup, filter_expresssion):
|
||||||
|
'''
|
||||||
|
Retrieves the list of supported metrics for this namespace and relay
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
relay_name: Name of the service bus relay in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
rollup: name of a supported rollup
|
||||||
|
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_data_relay_path(name, relay_name, metric, rollup, filter_expresssion),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricValues))
|
||||||
|
|
||||||
|
def get_metrics_rollups_queue(self, name, queue_name, metric):
|
||||||
|
'''
|
||||||
|
This operation gets rollup data for Service Bus metrics queue.
|
||||||
|
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||||
|
the retention settings for each time granularity.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
queue_name: Name of the service bus queue in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_rollup_queue_path(name, queue_name, metric),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricRollups))
|
||||||
|
|
||||||
|
def get_metrics_rollups_topic(self, name, topic_name, metric):
|
||||||
|
'''
|
||||||
|
This operation gets rollup data for Service Bus metrics topic.
|
||||||
|
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||||
|
the retention settings for each time granularity.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
topic_name: Name of the service bus queue in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_rollup_topic_path(name, topic_name, metric),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricRollups))
|
||||||
|
|
||||||
|
def get_metrics_rollups_notification_hub(self, name, hub_name, metric):
|
||||||
|
'''
|
||||||
|
This operation gets rollup data for Service Bus metrics notification hub.
|
||||||
|
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||||
|
the retention settings for each time granularity.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
hub_name: Name of the service bus notification hub in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_rollup_hub_path(name, hub_name, metric),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricRollups))
|
||||||
|
|
||||||
|
def get_metrics_rollups_relay(self, name, relay_name, metric):
|
||||||
|
'''
|
||||||
|
This operation gets rollup data for Service Bus metrics relay.
|
||||||
|
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||||
|
the retention settings for each time granularity.
|
||||||
|
|
||||||
|
name: Name of the service bus namespace.
|
||||||
|
relay_name: Name of the service bus relay in this namespace.
|
||||||
|
metric: name of a supported metric
|
||||||
|
'''
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_get_metrics_rollup_relay_path(name, relay_name, metric),
|
||||||
|
None)
|
||||||
|
|
||||||
|
return _convert_response_to_feeds(response,
|
||||||
|
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||||
|
object_type=MetricRollups))
|
||||||
|
|
||||||
|
|
||||||
|
# Helper functions --------------------------------------------------
|
||||||
|
def _get_list_queues_path(self, namespace_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/Queues'
|
||||||
|
|
||||||
|
def _get_list_topics_path(self, namespace_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/Topics'
|
||||||
|
|
||||||
|
def _get_list_notification_hubs_path(self, namespace_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/NotificationHubs'
|
||||||
|
|
||||||
|
def _get_list_relays_path(self, namespace_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/Relays'
|
||||||
|
|
||||||
|
def _get_get_supported_metrics_queue_path(self, namespace_name, queue_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/Queues/' + _str(queue_name) + '/Metrics'
|
||||||
|
|
||||||
|
def _get_get_supported_metrics_topic_path(self, namespace_name, topic_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/Topics/' + _str(topic_name) + '/Metrics'
|
||||||
|
|
||||||
|
def _get_get_supported_metrics_hub_path(self, namespace_name, hub_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/NotificationHubs/' + _str(hub_name) + '/Metrics'
|
||||||
|
|
||||||
|
def _get_get_supported_metrics_relay_path(self, namespace_name, queue_name):
|
||||||
|
return self._get_path('services/serviceBus/Namespaces/',
|
||||||
|
namespace_name) + '/Relays/' + _str(queue_name) + '/Metrics'
|
||||||
|
|
||||||
|
def _get_get_metrics_data_queue_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/Queues/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups/',
|
||||||
|
_str(rollup),
|
||||||
|
'/Values?',
|
||||||
|
filter_expr
|
||||||
|
])
|
||||||
|
|
||||||
|
def _get_get_metrics_data_topic_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/Topics/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups/',
|
||||||
|
_str(rollup),
|
||||||
|
'/Values?',
|
||||||
|
filter_expr
|
||||||
|
])
|
||||||
|
|
||||||
|
def _get_get_metrics_data_hub_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/NotificationHubs/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups/',
|
||||||
|
_str(rollup),
|
||||||
|
'/Values?',
|
||||||
|
filter_expr
|
||||||
|
])
|
||||||
|
|
||||||
|
def _get_get_metrics_data_relay_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/Relays/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups/',
|
||||||
|
_str(rollup),
|
||||||
|
'/Values?',
|
||||||
|
filter_expr
|
||||||
|
])
|
||||||
|
|
||||||
|
def _get_get_metrics_rollup_queue_path(self, namespace_name, queue_name, metric):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/Queues/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups',
|
||||||
|
])
|
||||||
|
|
||||||
|
def _get_get_metrics_rollup_topic_path(self, namespace_name, queue_name, metric):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/Topics/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups',
|
||||||
|
])
|
||||||
|
|
||||||
|
def _get_get_metrics_rollup_hub_path(self, namespace_name, queue_name, metric):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/NotificationHubs/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups',
|
||||||
|
])
|
||||||
|
|
||||||
|
def _get_get_metrics_rollup_relay_path(self, namespace_name, queue_name, metric):
|
||||||
|
return "".join([
|
||||||
|
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||||
|
'/Relays/',
|
||||||
|
_str(queue_name),
|
||||||
|
'/Metrics/',
|
||||||
|
_str(metric),
|
||||||
|
'/Rollups',
|
||||||
|
])
|
||||||
|
|||||||
@@ -1,166 +1,258 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from azure import (
|
from azure import (
|
||||||
WindowsAzureError,
|
WindowsAzureError,
|
||||||
MANAGEMENT_HOST,
|
MANAGEMENT_HOST,
|
||||||
_get_request_body,
|
_get_request_body,
|
||||||
_parse_response,
|
_parse_response,
|
||||||
_str,
|
_str,
|
||||||
_update_request_uri_query,
|
_update_request_uri_query,
|
||||||
)
|
)
|
||||||
from azure.http import (
|
from azure.http import (
|
||||||
HTTPError,
|
HTTPError,
|
||||||
HTTPRequest,
|
HTTPRequest,
|
||||||
)
|
)
|
||||||
from azure.http.httpclient import _HTTPClient
|
from azure.http.httpclient import _HTTPClient
|
||||||
from azure.servicemanagement import (
|
from azure.servicemanagement import (
|
||||||
AZURE_MANAGEMENT_CERTFILE,
|
AZURE_MANAGEMENT_CERTFILE,
|
||||||
AZURE_MANAGEMENT_SUBSCRIPTIONID,
|
AZURE_MANAGEMENT_SUBSCRIPTIONID,
|
||||||
_management_error_handler,
|
_management_error_handler,
|
||||||
_parse_response_for_async_op,
|
parse_response_for_async_op,
|
||||||
_update_management_header,
|
X_MS_VERSION,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class _ServiceManagementClient(object):
|
class _ServiceManagementClient(object):
|
||||||
|
|
||||||
def __init__(self, subscription_id=None, cert_file=None,
|
def __init__(self, subscription_id=None, cert_file=None,
|
||||||
host=MANAGEMENT_HOST):
|
host=MANAGEMENT_HOST, request_session=None):
|
||||||
self.requestid = None
|
self.requestid = None
|
||||||
self.subscription_id = subscription_id
|
self.subscription_id = subscription_id
|
||||||
self.cert_file = cert_file
|
self.cert_file = cert_file
|
||||||
self.host = host
|
self.host = host
|
||||||
|
self.request_session = request_session
|
||||||
if not self.cert_file:
|
self.x_ms_version = X_MS_VERSION
|
||||||
if AZURE_MANAGEMENT_CERTFILE in os.environ:
|
self.content_type = 'application/atom+xml;type=entry;charset=utf-8'
|
||||||
self.cert_file = os.environ[AZURE_MANAGEMENT_CERTFILE]
|
|
||||||
|
if not self.cert_file and not request_session:
|
||||||
if not self.subscription_id:
|
if AZURE_MANAGEMENT_CERTFILE in os.environ:
|
||||||
if AZURE_MANAGEMENT_SUBSCRIPTIONID in os.environ:
|
self.cert_file = os.environ[AZURE_MANAGEMENT_CERTFILE]
|
||||||
self.subscription_id = os.environ[
|
|
||||||
AZURE_MANAGEMENT_SUBSCRIPTIONID]
|
if not self.subscription_id:
|
||||||
|
if AZURE_MANAGEMENT_SUBSCRIPTIONID in os.environ:
|
||||||
if not self.cert_file or not self.subscription_id:
|
self.subscription_id = os.environ[
|
||||||
raise WindowsAzureError(
|
AZURE_MANAGEMENT_SUBSCRIPTIONID]
|
||||||
'You need to provide subscription id and certificate file')
|
|
||||||
|
if not self.request_session:
|
||||||
self._httpclient = _HTTPClient(
|
if not self.cert_file or not self.subscription_id:
|
||||||
service_instance=self, cert_file=self.cert_file)
|
raise WindowsAzureError(
|
||||||
self._filter = self._httpclient.perform_request
|
'You need to provide subscription id and certificate file')
|
||||||
|
|
||||||
def with_filter(self, filter):
|
self._httpclient = _HTTPClient(
|
||||||
'''Returns a new service which will process requests with the
|
service_instance=self, cert_file=self.cert_file,
|
||||||
specified filter. Filtering operations can include logging, automatic
|
request_session=self.request_session)
|
||||||
retrying, etc... The filter is a lambda which receives the HTTPRequest
|
self._filter = self._httpclient.perform_request
|
||||||
and another lambda. The filter can perform any pre-processing on the
|
|
||||||
request, pass it off to the next lambda, and then perform any
|
def with_filter(self, filter):
|
||||||
post-processing on the response.'''
|
'''Returns a new service which will process requests with the
|
||||||
res = type(self)(self.subscription_id, self.cert_file, self.host)
|
specified filter. Filtering operations can include logging, automatic
|
||||||
old_filter = self._filter
|
retrying, etc... The filter is a lambda which receives the HTTPRequest
|
||||||
|
and another lambda. The filter can perform any pre-processing on the
|
||||||
def new_filter(request):
|
request, pass it off to the next lambda, and then perform any
|
||||||
return filter(request, old_filter)
|
post-processing on the response.'''
|
||||||
|
res = type(self)(self.subscription_id, self.cert_file, self.host,
|
||||||
res._filter = new_filter
|
self.request_session)
|
||||||
return res
|
old_filter = self._filter
|
||||||
|
|
||||||
def set_proxy(self, host, port, user=None, password=None):
|
def new_filter(request):
|
||||||
'''
|
return filter(request, old_filter)
|
||||||
Sets the proxy server host and port for the HTTP CONNECT Tunnelling.
|
|
||||||
|
res._filter = new_filter
|
||||||
host: Address of the proxy. Ex: '192.168.0.100'
|
return res
|
||||||
port: Port of the proxy. Ex: 6000
|
|
||||||
user: User for proxy authorization.
|
def set_proxy(self, host, port, user=None, password=None):
|
||||||
password: Password for proxy authorization.
|
'''
|
||||||
'''
|
Sets the proxy server host and port for the HTTP CONNECT Tunnelling.
|
||||||
self._httpclient.set_proxy(host, port, user, password)
|
|
||||||
|
host: Address of the proxy. Ex: '192.168.0.100'
|
||||||
#--Helper functions --------------------------------------------------
|
port: Port of the proxy. Ex: 6000
|
||||||
def _perform_request(self, request):
|
user: User for proxy authorization.
|
||||||
try:
|
password: Password for proxy authorization.
|
||||||
resp = self._filter(request)
|
'''
|
||||||
except HTTPError as ex:
|
self._httpclient.set_proxy(host, port, user, password)
|
||||||
return _management_error_handler(ex)
|
|
||||||
|
def perform_get(self, path, x_ms_version=None):
|
||||||
return resp
|
'''
|
||||||
|
Performs a GET request and returns the response.
|
||||||
def _perform_get(self, path, response_type):
|
|
||||||
request = HTTPRequest()
|
path:
|
||||||
request.method = 'GET'
|
Path to the resource.
|
||||||
request.host = self.host
|
Ex: '/<subscription-id>/services/hostedservices/<service-name>'
|
||||||
request.path = path
|
x_ms_version:
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
If specified, this is used for the x-ms-version header.
|
||||||
request.headers = _update_management_header(request)
|
Otherwise, self.x_ms_version is used.
|
||||||
response = self._perform_request(request)
|
'''
|
||||||
|
request = HTTPRequest()
|
||||||
if response_type is not None:
|
request.method = 'GET'
|
||||||
return _parse_response(response, response_type)
|
request.host = self.host
|
||||||
|
request.path = path
|
||||||
return response
|
request.path, request.query = _update_request_uri_query(request)
|
||||||
|
request.headers = self._update_management_header(request, x_ms_version)
|
||||||
def _perform_put(self, path, body, async=False):
|
response = self._perform_request(request)
|
||||||
request = HTTPRequest()
|
|
||||||
request.method = 'PUT'
|
return response
|
||||||
request.host = self.host
|
|
||||||
request.path = path
|
def perform_put(self, path, body, x_ms_version=None):
|
||||||
request.body = _get_request_body(body)
|
'''
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
Performs a PUT request and returns the response.
|
||||||
request.headers = _update_management_header(request)
|
|
||||||
response = self._perform_request(request)
|
path:
|
||||||
|
Path to the resource.
|
||||||
if async:
|
Ex: '/<subscription-id>/services/hostedservices/<service-name>'
|
||||||
return _parse_response_for_async_op(response)
|
body:
|
||||||
|
Body for the PUT request.
|
||||||
return None
|
x_ms_version:
|
||||||
|
If specified, this is used for the x-ms-version header.
|
||||||
def _perform_post(self, path, body, response_type=None, async=False):
|
Otherwise, self.x_ms_version is used.
|
||||||
request = HTTPRequest()
|
'''
|
||||||
request.method = 'POST'
|
request = HTTPRequest()
|
||||||
request.host = self.host
|
request.method = 'PUT'
|
||||||
request.path = path
|
request.host = self.host
|
||||||
request.body = _get_request_body(body)
|
request.path = path
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
request.body = _get_request_body(body)
|
||||||
request.headers = _update_management_header(request)
|
request.path, request.query = _update_request_uri_query(request)
|
||||||
response = self._perform_request(request)
|
request.headers = self._update_management_header(request, x_ms_version)
|
||||||
|
response = self._perform_request(request)
|
||||||
if response_type is not None:
|
|
||||||
return _parse_response(response, response_type)
|
return response
|
||||||
|
|
||||||
if async:
|
def perform_post(self, path, body, x_ms_version=None):
|
||||||
return _parse_response_for_async_op(response)
|
'''
|
||||||
|
Performs a POST request and returns the response.
|
||||||
return None
|
|
||||||
|
path:
|
||||||
def _perform_delete(self, path, async=False):
|
Path to the resource.
|
||||||
request = HTTPRequest()
|
Ex: '/<subscription-id>/services/hostedservices/<service-name>'
|
||||||
request.method = 'DELETE'
|
body:
|
||||||
request.host = self.host
|
Body for the POST request.
|
||||||
request.path = path
|
x_ms_version:
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
If specified, this is used for the x-ms-version header.
|
||||||
request.headers = _update_management_header(request)
|
Otherwise, self.x_ms_version is used.
|
||||||
response = self._perform_request(request)
|
'''
|
||||||
|
request = HTTPRequest()
|
||||||
if async:
|
request.method = 'POST'
|
||||||
return _parse_response_for_async_op(response)
|
request.host = self.host
|
||||||
|
request.path = path
|
||||||
return None
|
request.body = _get_request_body(body)
|
||||||
|
request.path, request.query = _update_request_uri_query(request)
|
||||||
def _get_path(self, resource, name):
|
request.headers = self._update_management_header(request, x_ms_version)
|
||||||
path = '/' + self.subscription_id + '/' + resource
|
response = self._perform_request(request)
|
||||||
if name is not None:
|
|
||||||
path += '/' + _str(name)
|
return response
|
||||||
return path
|
|
||||||
|
def perform_delete(self, path, x_ms_version=None):
|
||||||
|
'''
|
||||||
|
Performs a DELETE request and returns the response.
|
||||||
|
|
||||||
|
path:
|
||||||
|
Path to the resource.
|
||||||
|
Ex: '/<subscription-id>/services/hostedservices/<service-name>'
|
||||||
|
x_ms_version:
|
||||||
|
If specified, this is used for the x-ms-version header.
|
||||||
|
Otherwise, self.x_ms_version is used.
|
||||||
|
'''
|
||||||
|
request = HTTPRequest()
|
||||||
|
request.method = 'DELETE'
|
||||||
|
request.host = self.host
|
||||||
|
request.path = path
|
||||||
|
request.path, request.query = _update_request_uri_query(request)
|
||||||
|
request.headers = self._update_management_header(request, x_ms_version)
|
||||||
|
response = self._perform_request(request)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
#--Helper functions --------------------------------------------------
|
||||||
|
def _perform_request(self, request):
|
||||||
|
try:
|
||||||
|
resp = self._filter(request)
|
||||||
|
except HTTPError as ex:
|
||||||
|
return _management_error_handler(ex)
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def _update_management_header(self, request, x_ms_version):
|
||||||
|
''' Add additional headers for management. '''
|
||||||
|
|
||||||
|
if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']:
|
||||||
|
request.headers.append(('Content-Length', str(len(request.body))))
|
||||||
|
|
||||||
|
# append additional headers base on the service
|
||||||
|
request.headers.append(('x-ms-version', x_ms_version or self.x_ms_version))
|
||||||
|
|
||||||
|
# if it is not GET or HEAD request, must set content-type.
|
||||||
|
if not request.method in ['GET', 'HEAD']:
|
||||||
|
for name, _ in request.headers:
|
||||||
|
if 'content-type' == name.lower():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
request.headers.append(
|
||||||
|
('Content-Type',
|
||||||
|
self.content_type))
|
||||||
|
|
||||||
|
return request.headers
|
||||||
|
|
||||||
|
def _perform_get(self, path, response_type, x_ms_version=None):
|
||||||
|
response = self.perform_get(path, x_ms_version)
|
||||||
|
|
||||||
|
if response_type is not None:
|
||||||
|
return _parse_response(response, response_type)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def _perform_put(self, path, body, async=False, x_ms_version=None):
|
||||||
|
response = self.perform_put(path, body, x_ms_version)
|
||||||
|
|
||||||
|
if async:
|
||||||
|
return parse_response_for_async_op(response)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _perform_post(self, path, body, response_type=None, async=False,
|
||||||
|
x_ms_version=None):
|
||||||
|
response = self.perform_post(path, body, x_ms_version)
|
||||||
|
|
||||||
|
if response_type is not None:
|
||||||
|
return _parse_response(response, response_type)
|
||||||
|
|
||||||
|
if async:
|
||||||
|
return parse_response_for_async_op(response)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _perform_delete(self, path, async=False, x_ms_version=None):
|
||||||
|
response = self.perform_delete(path, x_ms_version)
|
||||||
|
|
||||||
|
if async:
|
||||||
|
return parse_response_for_async_op(response)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_path(self, resource, name):
|
||||||
|
path = '/' + self.subscription_id + '/' + resource
|
||||||
|
if name is not None:
|
||||||
|
path += '/' + _str(name)
|
||||||
|
return path
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,390 @@
|
|||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
from azure import (
|
||||||
|
MANAGEMENT_HOST,
|
||||||
|
_parse_service_resources_response,
|
||||||
|
_validate_not_none,
|
||||||
|
)
|
||||||
|
from azure.servicemanagement import (
|
||||||
|
EventLog,
|
||||||
|
ServerQuota,
|
||||||
|
Servers,
|
||||||
|
ServiceObjective,
|
||||||
|
Database,
|
||||||
|
FirewallRule,
|
||||||
|
_SqlManagementXmlSerializer,
|
||||||
|
)
|
||||||
|
from azure.servicemanagement.servicemanagementclient import (
|
||||||
|
_ServiceManagementClient,
|
||||||
|
)
|
||||||
|
|
||||||
|
class SqlDatabaseManagementService(_ServiceManagementClient):
|
||||||
|
''' Note that this class is a preliminary work on SQL Database
|
||||||
|
management. Since it lack a lot a features, final version
|
||||||
|
can be slightly different from the current one.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, subscription_id=None, cert_file=None,
|
||||||
|
host=MANAGEMENT_HOST, request_session=None):
|
||||||
|
'''
|
||||||
|
Initializes the sql database management service.
|
||||||
|
|
||||||
|
subscription_id: Subscription to manage.
|
||||||
|
cert_file:
|
||||||
|
Path to .pem certificate file (httplib), or location of the
|
||||||
|
certificate in your Personal certificate store (winhttp) in the
|
||||||
|
CURRENT_USER\my\CertificateName format.
|
||||||
|
If a request_session is specified, then this is unused.
|
||||||
|
host: Live ServiceClient URL. Defaults to Azure public cloud.
|
||||||
|
request_session:
|
||||||
|
Session object to use for http requests. If this is specified, it
|
||||||
|
replaces the default use of httplib or winhttp. Also, the cert_file
|
||||||
|
parameter is unused when a session is passed in.
|
||||||
|
The session object handles authentication, and as such can support
|
||||||
|
multiple types of authentication: .pem certificate, oauth.
|
||||||
|
For example, you can pass in a Session instance from the requests
|
||||||
|
library. To use .pem certificate authentication with requests
|
||||||
|
library, set the path to the .pem file on the session.cert
|
||||||
|
attribute.
|
||||||
|
'''
|
||||||
|
super(SqlDatabaseManagementService, self).__init__(
|
||||||
|
subscription_id, cert_file, host, request_session)
|
||||||
|
self.content_type = 'application/xml'
|
||||||
|
|
||||||
|
#--Operations for sql servers ----------------------------------------
|
||||||
|
def create_server(self, admin_login, admin_password, location):
|
||||||
|
'''
|
||||||
|
Create a new Azure SQL Database server.
|
||||||
|
|
||||||
|
admin_login: The administrator login name for the new server.
|
||||||
|
admin_password: The administrator login password for the new server.
|
||||||
|
location: The region to deploy the new server.
|
||||||
|
'''
|
||||||
|
_validate_not_none('admin_login', admin_login)
|
||||||
|
_validate_not_none('admin_password', admin_password)
|
||||||
|
_validate_not_none('location', location)
|
||||||
|
response = self.perform_post(
|
||||||
|
self._get_servers_path(),
|
||||||
|
_SqlManagementXmlSerializer.create_server_to_xml(
|
||||||
|
admin_login,
|
||||||
|
admin_password,
|
||||||
|
location
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return _SqlManagementXmlSerializer.xml_to_create_server_response(
|
||||||
|
response.body)
|
||||||
|
|
||||||
|
def set_server_admin_password(self, server_name, admin_password):
|
||||||
|
'''
|
||||||
|
Reset the administrator password for a server.
|
||||||
|
|
||||||
|
server_name: Name of the server to change the password.
|
||||||
|
admin_password: The new administrator password for the server.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
_validate_not_none('admin_password', admin_password)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_servers_path(server_name) + '?op=ResetPassword',
|
||||||
|
_SqlManagementXmlSerializer.set_server_admin_password_to_xml(
|
||||||
|
admin_password
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_server(self, server_name):
|
||||||
|
'''
|
||||||
|
Deletes an Azure SQL Database server (including all its databases).
|
||||||
|
|
||||||
|
server_name: Name of the server you want to delete.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
return self._perform_delete(
|
||||||
|
self._get_servers_path(server_name))
|
||||||
|
|
||||||
|
def list_servers(self):
|
||||||
|
'''
|
||||||
|
List the SQL servers defined on the account.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_servers_path(),
|
||||||
|
Servers)
|
||||||
|
|
||||||
|
def list_quotas(self, server_name):
|
||||||
|
'''
|
||||||
|
Gets quotas for an Azure SQL Database Server.
|
||||||
|
|
||||||
|
server_name: Name of the server.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
response = self._perform_get(self._get_quotas_path(server_name),
|
||||||
|
None)
|
||||||
|
return _parse_service_resources_response(response, ServerQuota)
|
||||||
|
|
||||||
|
def get_server_event_logs(self, server_name, start_date,
|
||||||
|
interval_size_in_minutes, event_types=''):
|
||||||
|
'''
|
||||||
|
Gets the event logs for an Azure SQL Database Server.
|
||||||
|
|
||||||
|
server_name: Name of the server to retrieve the event logs from.
|
||||||
|
start_date:
|
||||||
|
The starting date and time of the events to retrieve in UTC format,
|
||||||
|
for example '2011-09-28 16:05:00'.
|
||||||
|
interval_size_in_minutes:
|
||||||
|
Size of the event logs to retrieve (in minutes).
|
||||||
|
Valid values are: 5, 60, or 1440.
|
||||||
|
event_types:
|
||||||
|
The event type of the log entries you want to retrieve.
|
||||||
|
Valid values are:
|
||||||
|
- connection_successful
|
||||||
|
- connection_failed
|
||||||
|
- connection_terminated
|
||||||
|
- deadlock
|
||||||
|
- throttling
|
||||||
|
- throttling_long_transaction
|
||||||
|
To return all event types pass in an empty string.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
_validate_not_none('start_date', start_date)
|
||||||
|
_validate_not_none('interval_size_in_minutes', interval_size_in_minutes)
|
||||||
|
_validate_not_none('event_types', event_types)
|
||||||
|
path = self._get_server_event_logs_path(server_name) + \
|
||||||
|
'?startDate={0}&intervalSizeInMinutes={1}&eventTypes={2}'.format(
|
||||||
|
start_date, interval_size_in_minutes, event_types)
|
||||||
|
response = self._perform_get(path, None)
|
||||||
|
return _parse_service_resources_response(response, EventLog)
|
||||||
|
|
||||||
|
#--Operations for firewall rules ------------------------------------------
|
||||||
|
def create_firewall_rule(self, server_name, name, start_ip_address,
|
||||||
|
end_ip_address):
|
||||||
|
'''
|
||||||
|
Creates an Azure SQL Database server firewall rule.
|
||||||
|
|
||||||
|
server_name: Name of the server to set the firewall rule on.
|
||||||
|
name: The name of the new firewall rule.
|
||||||
|
start_ip_address:
|
||||||
|
The lowest IP address in the range of the server-level firewall
|
||||||
|
setting. IP addresses equal to or greater than this can attempt to
|
||||||
|
connect to the server. The lowest possible IP address is 0.0.0.0.
|
||||||
|
end_ip_address:
|
||||||
|
The highest IP address in the range of the server-level firewall
|
||||||
|
setting. IP addresses equal to or less than this can attempt to
|
||||||
|
connect to the server. The highest possible IP address is
|
||||||
|
255.255.255.255.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
_validate_not_none('start_ip_address', start_ip_address)
|
||||||
|
_validate_not_none('end_ip_address', end_ip_address)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_firewall_rules_path(server_name),
|
||||||
|
_SqlManagementXmlSerializer.create_firewall_rule_to_xml(
|
||||||
|
name, start_ip_address, end_ip_address
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_firewall_rule(self, server_name, name, start_ip_address,
|
||||||
|
end_ip_address):
|
||||||
|
'''
|
||||||
|
Update a firewall rule for an Azure SQL Database server.
|
||||||
|
|
||||||
|
server_name: Name of the server to set the firewall rule on.
|
||||||
|
name: The name of the firewall rule to update.
|
||||||
|
start_ip_address:
|
||||||
|
The lowest IP address in the range of the server-level firewall
|
||||||
|
setting. IP addresses equal to or greater than this can attempt to
|
||||||
|
connect to the server. The lowest possible IP address is 0.0.0.0.
|
||||||
|
end_ip_address:
|
||||||
|
The highest IP address in the range of the server-level firewall
|
||||||
|
setting. IP addresses equal to or less than this can attempt to
|
||||||
|
connect to the server. The highest possible IP address is
|
||||||
|
255.255.255.255.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
_validate_not_none('start_ip_address', start_ip_address)
|
||||||
|
_validate_not_none('end_ip_address', end_ip_address)
|
||||||
|
return self._perform_put(
|
||||||
|
self._get_firewall_rules_path(server_name, name),
|
||||||
|
_SqlManagementXmlSerializer.update_firewall_rule_to_xml(
|
||||||
|
name, start_ip_address, end_ip_address
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_firewall_rule(self, server_name, name):
|
||||||
|
'''
|
||||||
|
Deletes an Azure SQL Database server firewall rule.
|
||||||
|
|
||||||
|
server_name:
|
||||||
|
Name of the server with the firewall rule you want to delete.
|
||||||
|
name:
|
||||||
|
Name of the firewall rule you want to delete.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
return self._perform_delete(
|
||||||
|
self._get_firewall_rules_path(server_name, name))
|
||||||
|
|
||||||
|
def list_firewall_rules(self, server_name):
|
||||||
|
'''
|
||||||
|
Retrieves the set of firewall rules for an Azure SQL Database Server.
|
||||||
|
|
||||||
|
server_name: Name of the server.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
response = self._perform_get(self._get_firewall_rules_path(server_name),
|
||||||
|
None)
|
||||||
|
return _parse_service_resources_response(response, FirewallRule)
|
||||||
|
|
||||||
|
def list_service_level_objectives(self, server_name):
|
||||||
|
'''
|
||||||
|
Gets the service level objectives for an Azure SQL Database server.
|
||||||
|
|
||||||
|
server_name: Name of the server.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
response = self._perform_get(
|
||||||
|
self._get_service_objectives_path(server_name), None)
|
||||||
|
return _parse_service_resources_response(response, ServiceObjective)
|
||||||
|
|
||||||
|
#--Operations for sql databases ----------------------------------------
|
||||||
|
def create_database(self, server_name, name, service_objective_id,
|
||||||
|
edition=None, collation_name=None,
|
||||||
|
max_size_bytes=None):
|
||||||
|
'''
|
||||||
|
Creates a new Azure SQL Database.
|
||||||
|
|
||||||
|
server_name: Name of the server to contain the new database.
|
||||||
|
name:
|
||||||
|
Required. The name for the new database. See Naming Requirements
|
||||||
|
in Azure SQL Database General Guidelines and Limitations and
|
||||||
|
Database Identifiers for more information.
|
||||||
|
service_objective_id:
|
||||||
|
Required. The GUID corresponding to the performance level for
|
||||||
|
Edition. See List Service Level Objectives for current values.
|
||||||
|
edition:
|
||||||
|
Optional. The Service Tier (Edition) for the new database. If
|
||||||
|
omitted, the default is Web. Valid values are Web, Business,
|
||||||
|
Basic, Standard, and Premium. See Azure SQL Database Service Tiers
|
||||||
|
(Editions) and Web and Business Edition Sunset FAQ for more
|
||||||
|
information.
|
||||||
|
collation_name:
|
||||||
|
Optional. The database collation. This can be any collation
|
||||||
|
supported by SQL. If omitted, the default collation is used. See
|
||||||
|
SQL Server Collation Support in Azure SQL Database General
|
||||||
|
Guidelines and Limitations for more information.
|
||||||
|
max_size_bytes:
|
||||||
|
Optional. Sets the maximum size, in bytes, for the database. This
|
||||||
|
value must be within the range of allowed values for Edition. If
|
||||||
|
omitted, the default value for the edition is used. See Azure SQL
|
||||||
|
Database Service Tiers (Editions) for current maximum databases
|
||||||
|
sizes. Convert MB or GB values to bytes.
|
||||||
|
1 MB = 1048576 bytes. 1 GB = 1073741824 bytes.
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
_validate_not_none('service_objective_id', service_objective_id)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_databases_path(server_name),
|
||||||
|
_SqlManagementXmlSerializer.create_database_to_xml(
|
||||||
|
name, service_objective_id, edition, collation_name,
|
||||||
|
max_size_bytes
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_database(self, server_name, name, new_database_name=None,
|
||||||
|
service_objective_id=None, edition=None,
|
||||||
|
max_size_bytes=None):
|
||||||
|
'''
|
||||||
|
Updates existing database details.
|
||||||
|
|
||||||
|
server_name: Name of the server to contain the new database.
|
||||||
|
name:
|
||||||
|
Required. The name for the new database. See Naming Requirements
|
||||||
|
in Azure SQL Database General Guidelines and Limitations and
|
||||||
|
Database Identifiers for more information.
|
||||||
|
new_database_name:
|
||||||
|
Optional. The new name for the new database.
|
||||||
|
service_objective_id:
|
||||||
|
Optional. The new service level to apply to the database. For more
|
||||||
|
information about service levels, see Azure SQL Database Service
|
||||||
|
Tiers and Performance Levels. Use List Service Level Objectives to
|
||||||
|
get the correct ID for the desired service objective.
|
||||||
|
edition:
|
||||||
|
Optional. The new edition for the new database.
|
||||||
|
max_size_bytes:
|
||||||
|
Optional. The new size of the database in bytes. For information on
|
||||||
|
available sizes for each edition, see Azure SQL Database Service
|
||||||
|
Tiers (Editions).
|
||||||
|
'''
|
||||||
|
_validate_not_none('server_name', server_name)
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
return self._perform_put(
|
||||||
|
self._get_databases_path(server_name, name),
|
||||||
|
_SqlManagementXmlSerializer.update_database_to_xml(
|
||||||
|
new_database_name, service_objective_id, edition,
|
||||||
|
max_size_bytes
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_database(self, server_name, name):
|
||||||
|
'''
|
||||||
|
Deletes an Azure SQL Database.
|
||||||
|
|
||||||
|
server_name: Name of the server where the database is located.
|
||||||
|
name: Name of the database to delete.
|
||||||
|
'''
|
||||||
|
return self._perform_delete(self._get_databases_path(server_name, name))
|
||||||
|
|
||||||
|
def list_databases(self, name):
|
||||||
|
'''
|
||||||
|
List the SQL databases defined on the specified server name
|
||||||
|
'''
|
||||||
|
response = self._perform_get(self._get_list_databases_path(name),
|
||||||
|
None)
|
||||||
|
return _parse_service_resources_response(response, Database)
|
||||||
|
|
||||||
|
|
||||||
|
#--Helper functions --------------------------------------------------
|
||||||
|
def _get_servers_path(self, server_name=None):
|
||||||
|
return self._get_path('services/sqlservers/servers', server_name)
|
||||||
|
|
||||||
|
def _get_firewall_rules_path(self, server_name, name=None):
|
||||||
|
path = self._get_servers_path(server_name) + '/firewallrules'
|
||||||
|
if name:
|
||||||
|
path = path + '/' + name
|
||||||
|
return path
|
||||||
|
|
||||||
|
def _get_databases_path(self, server_name, name=None):
|
||||||
|
path = self._get_servers_path(server_name) + '/databases'
|
||||||
|
if name:
|
||||||
|
path = path + '/' + name
|
||||||
|
return path
|
||||||
|
|
||||||
|
def _get_server_event_logs_path(self, server_name):
|
||||||
|
return self._get_servers_path(server_name) + '/events'
|
||||||
|
|
||||||
|
def _get_service_objectives_path(self, server_name):
|
||||||
|
return self._get_servers_path(server_name) + '/serviceobjectives'
|
||||||
|
|
||||||
|
def _get_quotas_path(self, server_name, name=None):
|
||||||
|
path = self._get_servers_path(server_name) + '/serverquotas'
|
||||||
|
if name:
|
||||||
|
path = path + '/' + name
|
||||||
|
return path
|
||||||
|
|
||||||
|
def _get_list_databases_path(self, name):
|
||||||
|
# *contentview=generic is mandatory*
|
||||||
|
return self._get_path('services/sqlservers/servers/',
|
||||||
|
name) + '/databases?contentview=generic'
|
||||||
|
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
from azure import (
|
||||||
|
MANAGEMENT_HOST,
|
||||||
|
_str,
|
||||||
|
)
|
||||||
|
from azure.servicemanagement import (
|
||||||
|
WebSpaces,
|
||||||
|
WebSpace,
|
||||||
|
Sites,
|
||||||
|
Site,
|
||||||
|
MetricResponses,
|
||||||
|
MetricDefinitions,
|
||||||
|
PublishData,
|
||||||
|
_XmlSerializer,
|
||||||
|
)
|
||||||
|
from azure.servicemanagement.servicemanagementclient import (
|
||||||
|
_ServiceManagementClient,
|
||||||
|
)
|
||||||
|
|
||||||
|
class WebsiteManagementService(_ServiceManagementClient):
|
||||||
|
''' Note that this class is a preliminary work on WebSite
|
||||||
|
management. Since it lack a lot a features, final version
|
||||||
|
can be slightly different from the current one.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, subscription_id=None, cert_file=None,
|
||||||
|
host=MANAGEMENT_HOST, request_session=None):
|
||||||
|
'''
|
||||||
|
Initializes the website management service.
|
||||||
|
|
||||||
|
subscription_id: Subscription to manage.
|
||||||
|
cert_file:
|
||||||
|
Path to .pem certificate file (httplib), or location of the
|
||||||
|
certificate in your Personal certificate store (winhttp) in the
|
||||||
|
CURRENT_USER\my\CertificateName format.
|
||||||
|
If a request_session is specified, then this is unused.
|
||||||
|
host: Live ServiceClient URL. Defaults to Azure public cloud.
|
||||||
|
request_session:
|
||||||
|
Session object to use for http requests. If this is specified, it
|
||||||
|
replaces the default use of httplib or winhttp. Also, the cert_file
|
||||||
|
parameter is unused when a session is passed in.
|
||||||
|
The session object handles authentication, and as such can support
|
||||||
|
multiple types of authentication: .pem certificate, oauth.
|
||||||
|
For example, you can pass in a Session instance from the requests
|
||||||
|
library. To use .pem certificate authentication with requests
|
||||||
|
library, set the path to the .pem file on the session.cert
|
||||||
|
attribute.
|
||||||
|
'''
|
||||||
|
super(WebsiteManagementService, self).__init__(
|
||||||
|
subscription_id, cert_file, host, request_session)
|
||||||
|
|
||||||
|
#--Operations for web sites ----------------------------------------
|
||||||
|
def list_webspaces(self):
|
||||||
|
'''
|
||||||
|
List the webspaces defined on the account.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_list_webspaces_path(),
|
||||||
|
WebSpaces)
|
||||||
|
|
||||||
|
def get_webspace(self, webspace_name):
|
||||||
|
'''
|
||||||
|
Get details of a specific webspace.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_webspace_details_path(webspace_name),
|
||||||
|
WebSpace)
|
||||||
|
|
||||||
|
def list_sites(self, webspace_name):
|
||||||
|
'''
|
||||||
|
List the web sites defined on this webspace.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_sites_path(webspace_name),
|
||||||
|
Sites)
|
||||||
|
|
||||||
|
def get_site(self, webspace_name, website_name):
|
||||||
|
'''
|
||||||
|
List the web sites defined on this webspace.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_sites_details_path(webspace_name,
|
||||||
|
website_name),
|
||||||
|
Site)
|
||||||
|
|
||||||
|
def create_site(self, webspace_name, website_name, geo_region, host_names,
|
||||||
|
plan='VirtualDedicatedPlan', compute_mode='Shared',
|
||||||
|
server_farm=None, site_mode=None):
|
||||||
|
'''
|
||||||
|
Create a website.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
geo_region:
|
||||||
|
The geographical region of the webspace that will be created.
|
||||||
|
host_names:
|
||||||
|
An array of fully qualified domain names for website. Only one
|
||||||
|
hostname can be specified in the azurewebsites.net domain.
|
||||||
|
The hostname should match the name of the website. Custom domains
|
||||||
|
can only be specified for Shared or Standard websites.
|
||||||
|
plan:
|
||||||
|
This value must be 'VirtualDedicatedPlan'.
|
||||||
|
compute_mode:
|
||||||
|
This value should be 'Shared' for the Free or Paid Shared
|
||||||
|
offerings, or 'Dedicated' for the Standard offering. The default
|
||||||
|
value is 'Shared'. If you set it to 'Dedicated', you must specify
|
||||||
|
a value for the server_farm parameter.
|
||||||
|
server_farm:
|
||||||
|
The name of the Server Farm associated with this website. This is
|
||||||
|
a required value for Standard mode.
|
||||||
|
site_mode:
|
||||||
|
Can be None, 'Limited' or 'Basic'. This value is 'Limited' for the
|
||||||
|
Free offering, and 'Basic' for the Paid Shared offering. Standard
|
||||||
|
mode does not use the site_mode parameter; it uses the compute_mode
|
||||||
|
parameter.
|
||||||
|
'''
|
||||||
|
xml = _XmlSerializer.create_website_to_xml(webspace_name, website_name, geo_region, plan, host_names, compute_mode, server_farm, site_mode)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_sites_path(webspace_name),
|
||||||
|
xml,
|
||||||
|
Site)
|
||||||
|
|
||||||
|
def delete_site(self, webspace_name, website_name,
|
||||||
|
delete_empty_server_farm=False, delete_metrics=False):
|
||||||
|
'''
|
||||||
|
Delete a website.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
delete_empty_server_farm:
|
||||||
|
If the site being deleted is the last web site in a server farm,
|
||||||
|
you can delete the server farm by setting this to True.
|
||||||
|
delete_metrics:
|
||||||
|
To also delete the metrics for the site that you are deleting, you
|
||||||
|
can set this to True.
|
||||||
|
'''
|
||||||
|
path = self._get_sites_details_path(webspace_name, website_name)
|
||||||
|
query = ''
|
||||||
|
if delete_empty_server_farm:
|
||||||
|
query += '&deleteEmptyServerFarm=true'
|
||||||
|
if delete_metrics:
|
||||||
|
query += '&deleteMetrics=true'
|
||||||
|
if query:
|
||||||
|
path = path + '?' + query.lstrip('&')
|
||||||
|
return self._perform_delete(path)
|
||||||
|
|
||||||
|
def restart_site(self, webspace_name, website_name):
|
||||||
|
'''
|
||||||
|
Restart a web site.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
'''
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_restart_path(webspace_name, website_name),
|
||||||
|
'')
|
||||||
|
|
||||||
|
def get_historical_usage_metrics(self, webspace_name, website_name,
|
||||||
|
metrics = None, start_time=None, end_time=None, time_grain=None):
|
||||||
|
'''
|
||||||
|
Get historical usage metrics.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
metrics: Optional. List of metrics name. Otherwise, all metrics returned.
|
||||||
|
start_time: Optional. An ISO8601 date. Otherwise, current hour is used.
|
||||||
|
end_time: Optional. An ISO8601 date. Otherwise, current time is used.
|
||||||
|
time_grain: Optional. A rollup name, as P1D. OTherwise, default rollup for the metrics is used.
|
||||||
|
More information and metrics name at:
|
||||||
|
http://msdn.microsoft.com/en-us/library/azure/dn166964.aspx
|
||||||
|
'''
|
||||||
|
metrics = ('names='+','.join(metrics)) if metrics else ''
|
||||||
|
start_time = ('StartTime='+start_time) if start_time else ''
|
||||||
|
end_time = ('EndTime='+end_time) if end_time else ''
|
||||||
|
time_grain = ('TimeGrain='+time_grain) if time_grain else ''
|
||||||
|
parameters = ('&'.join(v for v in (metrics, start_time, end_time, time_grain) if v))
|
||||||
|
parameters = '?'+parameters if parameters else ''
|
||||||
|
return self._perform_get(self._get_historical_usage_metrics_path(webspace_name, website_name) + parameters,
|
||||||
|
MetricResponses)
|
||||||
|
|
||||||
|
def get_metric_definitions(self, webspace_name, website_name):
|
||||||
|
'''
|
||||||
|
Get metric definitions of metrics available of this web site.
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_metric_definitions_path(webspace_name, website_name),
|
||||||
|
MetricDefinitions)
|
||||||
|
|
||||||
|
def get_publish_profile_xml(self, webspace_name, website_name):
|
||||||
|
'''
|
||||||
|
Get a site's publish profile as a string
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_publishxml_path(webspace_name, website_name),
|
||||||
|
None).body.decode("utf-8")
|
||||||
|
|
||||||
|
def get_publish_profile(self, webspace_name, website_name):
|
||||||
|
'''
|
||||||
|
Get a site's publish profile as an object
|
||||||
|
|
||||||
|
webspace_name: The name of the webspace.
|
||||||
|
website_name: The name of the website.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_publishxml_path(webspace_name, website_name),
|
||||||
|
PublishData)
|
||||||
|
|
||||||
|
#--Helper functions --------------------------------------------------
|
||||||
|
def _get_list_webspaces_path(self):
|
||||||
|
return self._get_path('services/webspaces', None)
|
||||||
|
|
||||||
|
def _get_webspace_details_path(self, webspace_name):
|
||||||
|
return self._get_path('services/webspaces/', webspace_name)
|
||||||
|
|
||||||
|
def _get_sites_path(self, webspace_name):
|
||||||
|
return self._get_path('services/webspaces/',
|
||||||
|
webspace_name) + '/sites'
|
||||||
|
|
||||||
|
def _get_sites_details_path(self, webspace_name, website_name):
|
||||||
|
return self._get_path('services/webspaces/',
|
||||||
|
webspace_name) + '/sites/' + _str(website_name)
|
||||||
|
|
||||||
|
def _get_restart_path(self, webspace_name, website_name):
|
||||||
|
return self._get_path('services/webspaces/',
|
||||||
|
webspace_name) + '/sites/' + _str(website_name) + '/restart/'
|
||||||
|
|
||||||
|
def _get_historical_usage_metrics_path(self, webspace_name, website_name):
|
||||||
|
return self._get_path('services/webspaces/',
|
||||||
|
webspace_name) + '/sites/' + _str(website_name) + '/metrics/'
|
||||||
|
|
||||||
|
def _get_metric_definitions_path(self, webspace_name, website_name):
|
||||||
|
return self._get_path('services/webspaces/',
|
||||||
|
webspace_name) + '/sites/' + _str(website_name) + '/metricdefinitions/'
|
||||||
|
|
||||||
|
def _get_publishxml_path(self, webspace_name, website_name):
|
||||||
|
return self._get_path('services/webspaces/',
|
||||||
|
webspace_name) + '/sites/' + _str(website_name) + '/publishxml/'
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,39 +1,39 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
from azure.storage.blobservice import BlobService
|
from azure.storage.blobservice import BlobService
|
||||||
from azure.storage.tableservice import TableService
|
from azure.storage.tableservice import TableService
|
||||||
from azure.storage.queueservice import QueueService
|
from azure.storage.queueservice import QueueService
|
||||||
|
|
||||||
|
|
||||||
class CloudStorageAccount(object):
|
class CloudStorageAccount(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Provides a factory for creating the blob, queue, and table services
|
Provides a factory for creating the blob, queue, and table services
|
||||||
with a common account name and account key. Users can either use the
|
with a common account name and account key. Users can either use the
|
||||||
factory or can construct the appropriate service directly.
|
factory or can construct the appropriate service directly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, account_name=None, account_key=None):
|
def __init__(self, account_name=None, account_key=None):
|
||||||
self.account_name = account_name
|
self.account_name = account_name
|
||||||
self.account_key = account_key
|
self.account_key = account_key
|
||||||
|
|
||||||
def create_blob_service(self):
|
def create_blob_service(self):
|
||||||
return BlobService(self.account_name, self.account_key)
|
return BlobService(self.account_name, self.account_key)
|
||||||
|
|
||||||
def create_table_service(self):
|
def create_table_service(self):
|
||||||
return TableService(self.account_name, self.account_key)
|
return TableService(self.account_name, self.account_key)
|
||||||
|
|
||||||
def create_queue_service(self):
|
def create_queue_service(self):
|
||||||
return QueueService(self.account_name, self.account_key)
|
return QueueService(self.account_name, self.account_key)
|
||||||
|
|||||||
@@ -1,458 +1,458 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
from azure import (
|
from azure import (
|
||||||
WindowsAzureConflictError,
|
WindowsAzureConflictError,
|
||||||
WindowsAzureError,
|
WindowsAzureError,
|
||||||
DEV_QUEUE_HOST,
|
DEV_QUEUE_HOST,
|
||||||
QUEUE_SERVICE_HOST_BASE,
|
QUEUE_SERVICE_HOST_BASE,
|
||||||
xml_escape,
|
xml_escape,
|
||||||
_convert_class_to_xml,
|
_convert_class_to_xml,
|
||||||
_dont_fail_not_exist,
|
_dont_fail_not_exist,
|
||||||
_dont_fail_on_exist,
|
_dont_fail_on_exist,
|
||||||
_get_request_body,
|
_get_request_body,
|
||||||
_int_or_none,
|
_int_or_none,
|
||||||
_parse_enum_results_list,
|
_parse_enum_results_list,
|
||||||
_parse_response,
|
_parse_response,
|
||||||
_parse_response_for_dict_filter,
|
_parse_response_for_dict_filter,
|
||||||
_parse_response_for_dict_prefix,
|
_parse_response_for_dict_prefix,
|
||||||
_str,
|
_str,
|
||||||
_str_or_none,
|
_str_or_none,
|
||||||
_update_request_uri_query_local_storage,
|
_update_request_uri_query_local_storage,
|
||||||
_validate_not_none,
|
_validate_not_none,
|
||||||
_ERROR_CONFLICT,
|
_ERROR_CONFLICT,
|
||||||
)
|
)
|
||||||
from azure.http import (
|
from azure.http import (
|
||||||
HTTPRequest,
|
HTTPRequest,
|
||||||
HTTP_RESPONSE_NO_CONTENT,
|
HTTP_RESPONSE_NO_CONTENT,
|
||||||
)
|
)
|
||||||
from azure.storage import (
|
from azure.storage import (
|
||||||
Queue,
|
Queue,
|
||||||
QueueEnumResults,
|
QueueEnumResults,
|
||||||
QueueMessagesList,
|
QueueMessagesList,
|
||||||
StorageServiceProperties,
|
StorageServiceProperties,
|
||||||
_update_storage_queue_header,
|
_update_storage_queue_header,
|
||||||
)
|
)
|
||||||
from azure.storage.storageclient import _StorageClient
|
from azure.storage.storageclient import _StorageClient
|
||||||
|
|
||||||
|
|
||||||
class QueueService(_StorageClient):
|
class QueueService(_StorageClient):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
This is the main class managing queue resources.
|
This is the main class managing queue resources.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, account_name=None, account_key=None, protocol='https',
|
def __init__(self, account_name=None, account_key=None, protocol='https',
|
||||||
host_base=QUEUE_SERVICE_HOST_BASE, dev_host=DEV_QUEUE_HOST):
|
host_base=QUEUE_SERVICE_HOST_BASE, dev_host=DEV_QUEUE_HOST):
|
||||||
'''
|
'''
|
||||||
account_name: your storage account name, required for all operations.
|
account_name: your storage account name, required for all operations.
|
||||||
account_key: your storage account key, required for all operations.
|
account_key: your storage account key, required for all operations.
|
||||||
protocol: Optional. Protocol. Defaults to http.
|
protocol: Optional. Protocol. Defaults to http.
|
||||||
host_base:
|
host_base:
|
||||||
Optional. Live host base url. Defaults to Azure url. Override this
|
Optional. Live host base url. Defaults to Azure url. Override this
|
||||||
for on-premise.
|
for on-premise.
|
||||||
dev_host: Optional. Dev host url. Defaults to localhost.
|
dev_host: Optional. Dev host url. Defaults to localhost.
|
||||||
'''
|
'''
|
||||||
super(QueueService, self).__init__(
|
super(QueueService, self).__init__(
|
||||||
account_name, account_key, protocol, host_base, dev_host)
|
account_name, account_key, protocol, host_base, dev_host)
|
||||||
|
|
||||||
def get_queue_service_properties(self, timeout=None):
|
def get_queue_service_properties(self, timeout=None):
|
||||||
'''
|
'''
|
||||||
Gets the properties of a storage account's Queue Service, including
|
Gets the properties of a storage account's Queue Service, including
|
||||||
Windows Azure Storage Analytics.
|
Windows Azure Storage Analytics.
|
||||||
|
|
||||||
timeout: Optional. The timeout parameter is expressed in seconds.
|
timeout: Optional. The timeout parameter is expressed in seconds.
|
||||||
'''
|
'''
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/?restype=service&comp=properties'
|
request.path = '/?restype=service&comp=properties'
|
||||||
request.query = [('timeout', _int_or_none(timeout))]
|
request.query = [('timeout', _int_or_none(timeout))]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response(response, StorageServiceProperties)
|
return _parse_response(response, StorageServiceProperties)
|
||||||
|
|
||||||
def list_queues(self, prefix=None, marker=None, maxresults=None,
|
def list_queues(self, prefix=None, marker=None, maxresults=None,
|
||||||
include=None):
|
include=None):
|
||||||
'''
|
'''
|
||||||
Lists all of the queues in a given storage account.
|
Lists all of the queues in a given storage account.
|
||||||
|
|
||||||
prefix:
|
prefix:
|
||||||
Filters the results to return only queues with names that begin
|
Filters the results to return only queues with names that begin
|
||||||
with the specified prefix.
|
with the specified prefix.
|
||||||
marker:
|
marker:
|
||||||
A string value that identifies the portion of the list to be
|
A string value that identifies the portion of the list to be
|
||||||
returned with the next list operation. The operation returns a
|
returned with the next list operation. The operation returns a
|
||||||
NextMarker element within the response body if the list returned
|
NextMarker element within the response body if the list returned
|
||||||
was not complete. This value may then be used as a query parameter
|
was not complete. This value may then be used as a query parameter
|
||||||
in a subsequent call to request the next portion of the list of
|
in a subsequent call to request the next portion of the list of
|
||||||
queues. The marker value is opaque to the client.
|
queues. The marker value is opaque to the client.
|
||||||
maxresults:
|
maxresults:
|
||||||
Specifies the maximum number of queues to return. If maxresults is
|
Specifies the maximum number of queues to return. If maxresults is
|
||||||
not specified, the server will return up to 5,000 items.
|
not specified, the server will return up to 5,000 items.
|
||||||
include:
|
include:
|
||||||
Optional. Include this parameter to specify that the container's
|
Optional. Include this parameter to specify that the container's
|
||||||
metadata be returned as part of the response body.
|
metadata be returned as part of the response body.
|
||||||
'''
|
'''
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/?comp=list'
|
request.path = '/?comp=list'
|
||||||
request.query = [
|
request.query = [
|
||||||
('prefix', _str_or_none(prefix)),
|
('prefix', _str_or_none(prefix)),
|
||||||
('marker', _str_or_none(marker)),
|
('marker', _str_or_none(marker)),
|
||||||
('maxresults', _int_or_none(maxresults)),
|
('maxresults', _int_or_none(maxresults)),
|
||||||
('include', _str_or_none(include))
|
('include', _str_or_none(include))
|
||||||
]
|
]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_enum_results_list(
|
return _parse_enum_results_list(
|
||||||
response, QueueEnumResults, "Queues", Queue)
|
response, QueueEnumResults, "Queues", Queue)
|
||||||
|
|
||||||
def create_queue(self, queue_name, x_ms_meta_name_values=None,
|
def create_queue(self, queue_name, x_ms_meta_name_values=None,
|
||||||
fail_on_exist=False):
|
fail_on_exist=False):
|
||||||
'''
|
'''
|
||||||
Creates a queue under the given account.
|
Creates a queue under the given account.
|
||||||
|
|
||||||
queue_name: name of the queue.
|
queue_name: name of the queue.
|
||||||
x_ms_meta_name_values:
|
x_ms_meta_name_values:
|
||||||
Optional. A dict containing name-value pairs to associate with the
|
Optional. A dict containing name-value pairs to associate with the
|
||||||
queue as metadata.
|
queue as metadata.
|
||||||
fail_on_exist: Specify whether throw exception when queue exists.
|
fail_on_exist: Specify whether throw exception when queue exists.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'PUT'
|
request.method = 'PUT'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + ''
|
request.path = '/' + _str(queue_name) + ''
|
||||||
request.headers = [('x-ms-meta-name-values', x_ms_meta_name_values)]
|
request.headers = [('x-ms-meta-name-values', x_ms_meta_name_values)]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
if not fail_on_exist:
|
if not fail_on_exist:
|
||||||
try:
|
try:
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
if response.status == HTTP_RESPONSE_NO_CONTENT:
|
if response.status == HTTP_RESPONSE_NO_CONTENT:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
except WindowsAzureError as ex:
|
except WindowsAzureError as ex:
|
||||||
_dont_fail_on_exist(ex)
|
_dont_fail_on_exist(ex)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
if response.status == HTTP_RESPONSE_NO_CONTENT:
|
if response.status == HTTP_RESPONSE_NO_CONTENT:
|
||||||
raise WindowsAzureConflictError(
|
raise WindowsAzureConflictError(
|
||||||
_ERROR_CONFLICT.format(response.message))
|
_ERROR_CONFLICT.format(response.message))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def delete_queue(self, queue_name, fail_not_exist=False):
|
def delete_queue(self, queue_name, fail_not_exist=False):
|
||||||
'''
|
'''
|
||||||
Permanently deletes the specified queue.
|
Permanently deletes the specified queue.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
fail_not_exist:
|
fail_not_exist:
|
||||||
Specify whether throw exception when queue doesn't exist.
|
Specify whether throw exception when queue doesn't exist.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + ''
|
request.path = '/' + _str(queue_name) + ''
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
if not fail_not_exist:
|
if not fail_not_exist:
|
||||||
try:
|
try:
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
return True
|
return True
|
||||||
except WindowsAzureError as ex:
|
except WindowsAzureError as ex:
|
||||||
_dont_fail_not_exist(ex)
|
_dont_fail_not_exist(ex)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_queue_metadata(self, queue_name):
|
def get_queue_metadata(self, queue_name):
|
||||||
'''
|
'''
|
||||||
Retrieves user-defined metadata and queue properties on the specified
|
Retrieves user-defined metadata and queue properties on the specified
|
||||||
queue. Metadata is associated with the queue as name-values pairs.
|
queue. Metadata is associated with the queue as name-values pairs.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + '?comp=metadata'
|
request.path = '/' + _str(queue_name) + '?comp=metadata'
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response_for_dict_prefix(
|
return _parse_response_for_dict_prefix(
|
||||||
response,
|
response,
|
||||||
prefixes=['x-ms-meta', 'x-ms-approximate-messages-count'])
|
prefixes=['x-ms-meta', 'x-ms-approximate-messages-count'])
|
||||||
|
|
||||||
def set_queue_metadata(self, queue_name, x_ms_meta_name_values=None):
|
def set_queue_metadata(self, queue_name, x_ms_meta_name_values=None):
|
||||||
'''
|
'''
|
||||||
Sets user-defined metadata on the specified queue. Metadata is
|
Sets user-defined metadata on the specified queue. Metadata is
|
||||||
associated with the queue as name-value pairs.
|
associated with the queue as name-value pairs.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
x_ms_meta_name_values:
|
x_ms_meta_name_values:
|
||||||
Optional. A dict containing name-value pairs to associate with the
|
Optional. A dict containing name-value pairs to associate with the
|
||||||
queue as metadata.
|
queue as metadata.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'PUT'
|
request.method = 'PUT'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + '?comp=metadata'
|
request.path = '/' + _str(queue_name) + '?comp=metadata'
|
||||||
request.headers = [('x-ms-meta-name-values', x_ms_meta_name_values)]
|
request.headers = [('x-ms-meta-name-values', x_ms_meta_name_values)]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
|
|
||||||
def put_message(self, queue_name, message_text, visibilitytimeout=None,
|
def put_message(self, queue_name, message_text, visibilitytimeout=None,
|
||||||
messagettl=None):
|
messagettl=None):
|
||||||
'''
|
'''
|
||||||
Adds a new message to the back of the message queue. A visibility
|
Adds a new message to the back of the message queue. A visibility
|
||||||
timeout can also be specified to make the message invisible until the
|
timeout can also be specified to make the message invisible until the
|
||||||
visibility timeout expires. A message must be in a format that can be
|
visibility timeout expires. A message must be in a format that can be
|
||||||
included in an XML request with UTF-8 encoding. The encoded message can
|
included in an XML request with UTF-8 encoding. The encoded message can
|
||||||
be up to 64KB in size for versions 2011-08-18 and newer, or 8KB in size
|
be up to 64KB in size for versions 2011-08-18 and newer, or 8KB in size
|
||||||
for previous versions.
|
for previous versions.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
message_text: Message content.
|
message_text: Message content.
|
||||||
visibilitytimeout:
|
visibilitytimeout:
|
||||||
Optional. If not specified, the default value is 0. Specifies the
|
Optional. If not specified, the default value is 0. Specifies the
|
||||||
new visibility timeout value, in seconds, relative to server time.
|
new visibility timeout value, in seconds, relative to server time.
|
||||||
The new value must be larger than or equal to 0, and cannot be
|
The new value must be larger than or equal to 0, and cannot be
|
||||||
larger than 7 days. The visibility timeout of a message cannot be
|
larger than 7 days. The visibility timeout of a message cannot be
|
||||||
set to a value later than the expiry time. visibilitytimeout
|
set to a value later than the expiry time. visibilitytimeout
|
||||||
should be set to a value smaller than the time-to-live value.
|
should be set to a value smaller than the time-to-live value.
|
||||||
messagettl:
|
messagettl:
|
||||||
Optional. Specifies the time-to-live interval for the message, in
|
Optional. Specifies the time-to-live interval for the message, in
|
||||||
seconds. The maximum time-to-live allowed is 7 days. If this
|
seconds. The maximum time-to-live allowed is 7 days. If this
|
||||||
parameter is omitted, the default time-to-live is 7 days.
|
parameter is omitted, the default time-to-live is 7 days.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
_validate_not_none('message_text', message_text)
|
_validate_not_none('message_text', message_text)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + '/messages'
|
request.path = '/' + _str(queue_name) + '/messages'
|
||||||
request.query = [
|
request.query = [
|
||||||
('visibilitytimeout', _str_or_none(visibilitytimeout)),
|
('visibilitytimeout', _str_or_none(visibilitytimeout)),
|
||||||
('messagettl', _str_or_none(messagettl))
|
('messagettl', _str_or_none(messagettl))
|
||||||
]
|
]
|
||||||
request.body = _get_request_body(
|
request.body = _get_request_body(
|
||||||
'<?xml version="1.0" encoding="utf-8"?> \
|
'<?xml version="1.0" encoding="utf-8"?> \
|
||||||
<QueueMessage> \
|
<QueueMessage> \
|
||||||
<MessageText>' + xml_escape(_str(message_text)) + '</MessageText> \
|
<MessageText>' + xml_escape(_str(message_text)) + '</MessageText> \
|
||||||
</QueueMessage>')
|
</QueueMessage>')
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
|
|
||||||
def get_messages(self, queue_name, numofmessages=None,
|
def get_messages(self, queue_name, numofmessages=None,
|
||||||
visibilitytimeout=None):
|
visibilitytimeout=None):
|
||||||
'''
|
'''
|
||||||
Retrieves one or more messages from the front of the queue.
|
Retrieves one or more messages from the front of the queue.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
numofmessages:
|
numofmessages:
|
||||||
Optional. A nonzero integer value that specifies the number of
|
Optional. A nonzero integer value that specifies the number of
|
||||||
messages to retrieve from the queue, up to a maximum of 32. If
|
messages to retrieve from the queue, up to a maximum of 32. If
|
||||||
fewer are visible, the visible messages are returned. By default,
|
fewer are visible, the visible messages are returned. By default,
|
||||||
a single message is retrieved from the queue with this operation.
|
a single message is retrieved from the queue with this operation.
|
||||||
visibilitytimeout:
|
visibilitytimeout:
|
||||||
Specifies the new visibility timeout value, in seconds, relative
|
Specifies the new visibility timeout value, in seconds, relative
|
||||||
to server time. The new value must be larger than or equal to 1
|
to server time. The new value must be larger than or equal to 1
|
||||||
second, and cannot be larger than 7 days, or larger than 2 hours
|
second, and cannot be larger than 7 days, or larger than 2 hours
|
||||||
on REST protocol versions prior to version 2011-08-18. The
|
on REST protocol versions prior to version 2011-08-18. The
|
||||||
visibility timeout of a message can be set to a value later than
|
visibility timeout of a message can be set to a value later than
|
||||||
the expiry time.
|
the expiry time.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + '/messages'
|
request.path = '/' + _str(queue_name) + '/messages'
|
||||||
request.query = [
|
request.query = [
|
||||||
('numofmessages', _str_or_none(numofmessages)),
|
('numofmessages', _str_or_none(numofmessages)),
|
||||||
('visibilitytimeout', _str_or_none(visibilitytimeout))
|
('visibilitytimeout', _str_or_none(visibilitytimeout))
|
||||||
]
|
]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response(response, QueueMessagesList)
|
return _parse_response(response, QueueMessagesList)
|
||||||
|
|
||||||
def peek_messages(self, queue_name, numofmessages=None):
|
def peek_messages(self, queue_name, numofmessages=None):
|
||||||
'''
|
'''
|
||||||
Retrieves one or more messages from the front of the queue, but does
|
Retrieves one or more messages from the front of the queue, but does
|
||||||
not alter the visibility of the message.
|
not alter the visibility of the message.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
numofmessages:
|
numofmessages:
|
||||||
Optional. A nonzero integer value that specifies the number of
|
Optional. A nonzero integer value that specifies the number of
|
||||||
messages to peek from the queue, up to a maximum of 32. By default,
|
messages to peek from the queue, up to a maximum of 32. By default,
|
||||||
a single message is peeked from the queue with this operation.
|
a single message is peeked from the queue with this operation.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + '/messages?peekonly=true'
|
request.path = '/' + _str(queue_name) + '/messages?peekonly=true'
|
||||||
request.query = [('numofmessages', _str_or_none(numofmessages))]
|
request.query = [('numofmessages', _str_or_none(numofmessages))]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response(response, QueueMessagesList)
|
return _parse_response(response, QueueMessagesList)
|
||||||
|
|
||||||
def delete_message(self, queue_name, message_id, popreceipt):
|
def delete_message(self, queue_name, message_id, popreceipt):
|
||||||
'''
|
'''
|
||||||
Deletes the specified message.
|
Deletes the specified message.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
message_id: Message to delete.
|
message_id: Message to delete.
|
||||||
popreceipt:
|
popreceipt:
|
||||||
Required. A valid pop receipt value returned from an earlier call
|
Required. A valid pop receipt value returned from an earlier call
|
||||||
to the Get Messages or Update Message operation.
|
to the Get Messages or Update Message operation.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
_validate_not_none('message_id', message_id)
|
_validate_not_none('message_id', message_id)
|
||||||
_validate_not_none('popreceipt', popreceipt)
|
_validate_not_none('popreceipt', popreceipt)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + \
|
request.path = '/' + \
|
||||||
_str(queue_name) + '/messages/' + _str(message_id) + ''
|
_str(queue_name) + '/messages/' + _str(message_id) + ''
|
||||||
request.query = [('popreceipt', _str_or_none(popreceipt))]
|
request.query = [('popreceipt', _str_or_none(popreceipt))]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
|
|
||||||
def clear_messages(self, queue_name):
|
def clear_messages(self, queue_name):
|
||||||
'''
|
'''
|
||||||
Deletes all messages from the specified queue.
|
Deletes all messages from the specified queue.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(queue_name) + '/messages'
|
request.path = '/' + _str(queue_name) + '/messages'
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
|
|
||||||
def update_message(self, queue_name, message_id, message_text, popreceipt,
|
def update_message(self, queue_name, message_id, message_text, popreceipt,
|
||||||
visibilitytimeout):
|
visibilitytimeout):
|
||||||
'''
|
'''
|
||||||
Updates the visibility timeout of a message. You can also use this
|
Updates the visibility timeout of a message. You can also use this
|
||||||
operation to update the contents of a message.
|
operation to update the contents of a message.
|
||||||
|
|
||||||
queue_name: Name of the queue.
|
queue_name: Name of the queue.
|
||||||
message_id: Message to update.
|
message_id: Message to update.
|
||||||
message_text: Content of message.
|
message_text: Content of message.
|
||||||
popreceipt:
|
popreceipt:
|
||||||
Required. A valid pop receipt value returned from an earlier call
|
Required. A valid pop receipt value returned from an earlier call
|
||||||
to the Get Messages or Update Message operation.
|
to the Get Messages or Update Message operation.
|
||||||
visibilitytimeout:
|
visibilitytimeout:
|
||||||
Required. Specifies the new visibility timeout value, in seconds,
|
Required. Specifies the new visibility timeout value, in seconds,
|
||||||
relative to server time. The new value must be larger than or equal
|
relative to server time. The new value must be larger than or equal
|
||||||
to 0, and cannot be larger than 7 days. The visibility timeout of a
|
to 0, and cannot be larger than 7 days. The visibility timeout of a
|
||||||
message cannot be set to a value later than the expiry time. A
|
message cannot be set to a value later than the expiry time. A
|
||||||
message can be updated until it has been deleted or has expired.
|
message can be updated until it has been deleted or has expired.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('queue_name', queue_name)
|
_validate_not_none('queue_name', queue_name)
|
||||||
_validate_not_none('message_id', message_id)
|
_validate_not_none('message_id', message_id)
|
||||||
_validate_not_none('message_text', message_text)
|
_validate_not_none('message_text', message_text)
|
||||||
_validate_not_none('popreceipt', popreceipt)
|
_validate_not_none('popreceipt', popreceipt)
|
||||||
_validate_not_none('visibilitytimeout', visibilitytimeout)
|
_validate_not_none('visibilitytimeout', visibilitytimeout)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'PUT'
|
request.method = 'PUT'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + \
|
request.path = '/' + \
|
||||||
_str(queue_name) + '/messages/' + _str(message_id) + ''
|
_str(queue_name) + '/messages/' + _str(message_id) + ''
|
||||||
request.query = [
|
request.query = [
|
||||||
('popreceipt', _str_or_none(popreceipt)),
|
('popreceipt', _str_or_none(popreceipt)),
|
||||||
('visibilitytimeout', _str_or_none(visibilitytimeout))
|
('visibilitytimeout', _str_or_none(visibilitytimeout))
|
||||||
]
|
]
|
||||||
request.body = _get_request_body(
|
request.body = _get_request_body(
|
||||||
'<?xml version="1.0" encoding="utf-8"?> \
|
'<?xml version="1.0" encoding="utf-8"?> \
|
||||||
<QueueMessage> \
|
<QueueMessage> \
|
||||||
<MessageText>' + xml_escape(_str(message_text)) + '</MessageText> \
|
<MessageText>' + xml_escape(_str(message_text)) + '</MessageText> \
|
||||||
</QueueMessage>')
|
</QueueMessage>')
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response_for_dict_filter(
|
return _parse_response_for_dict_filter(
|
||||||
response,
|
response,
|
||||||
filter=['x-ms-popreceipt', 'x-ms-time-next-visible'])
|
filter=['x-ms-popreceipt', 'x-ms-time-next-visible'])
|
||||||
|
|
||||||
def set_queue_service_properties(self, storage_service_properties,
|
def set_queue_service_properties(self, storage_service_properties,
|
||||||
timeout=None):
|
timeout=None):
|
||||||
'''
|
'''
|
||||||
Sets the properties of a storage account's Queue service, including
|
Sets the properties of a storage account's Queue service, including
|
||||||
Windows Azure Storage Analytics.
|
Windows Azure Storage Analytics.
|
||||||
|
|
||||||
storage_service_properties: StorageServiceProperties object.
|
storage_service_properties: StorageServiceProperties object.
|
||||||
timeout: Optional. The timeout parameter is expressed in seconds.
|
timeout: Optional. The timeout parameter is expressed in seconds.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('storage_service_properties',
|
_validate_not_none('storage_service_properties',
|
||||||
storage_service_properties)
|
storage_service_properties)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'PUT'
|
request.method = 'PUT'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/?restype=service&comp=properties'
|
request.path = '/?restype=service&comp=properties'
|
||||||
request.query = [('timeout', _int_or_none(timeout))]
|
request.query = [('timeout', _int_or_none(timeout))]
|
||||||
request.body = _get_request_body(
|
request.body = _get_request_body(
|
||||||
_convert_class_to_xml(storage_service_properties))
|
_convert_class_to_xml(storage_service_properties))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_queue_header(
|
request.headers = _update_storage_queue_header(
|
||||||
request, self.account_name, self.account_key)
|
request, self.account_name, self.account_key)
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
|
|||||||
@@ -1,230 +1,231 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
from azure import url_quote
|
from azure import _sign_string, url_quote
|
||||||
from azure.storage import _sign_string, X_MS_VERSION
|
from azure.storage import X_MS_VERSION
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Constants for the share access signature
|
# Constants for the share access signature
|
||||||
SIGNED_START = 'st'
|
SIGNED_VERSION = 'sv'
|
||||||
SIGNED_EXPIRY = 'se'
|
SIGNED_START = 'st'
|
||||||
SIGNED_RESOURCE = 'sr'
|
SIGNED_EXPIRY = 'se'
|
||||||
SIGNED_PERMISSION = 'sp'
|
SIGNED_RESOURCE = 'sr'
|
||||||
SIGNED_IDENTIFIER = 'si'
|
SIGNED_PERMISSION = 'sp'
|
||||||
SIGNED_SIGNATURE = 'sig'
|
SIGNED_IDENTIFIER = 'si'
|
||||||
SIGNED_VERSION = 'sv'
|
SIGNED_SIGNATURE = 'sig'
|
||||||
RESOURCE_BLOB = 'b'
|
SIGNED_VERSION = 'sv'
|
||||||
RESOURCE_CONTAINER = 'c'
|
RESOURCE_BLOB = 'b'
|
||||||
SIGNED_RESOURCE_TYPE = 'resource'
|
RESOURCE_CONTAINER = 'c'
|
||||||
SHARED_ACCESS_PERMISSION = 'permission'
|
SIGNED_RESOURCE_TYPE = 'resource'
|
||||||
|
SHARED_ACCESS_PERMISSION = 'permission'
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
|
||||||
class WebResource(object):
|
|
||||||
|
class WebResource(object):
|
||||||
'''
|
|
||||||
Class that stands for the resource to get the share access signature
|
'''
|
||||||
|
Class that stands for the resource to get the share access signature
|
||||||
path: the resource path.
|
|
||||||
properties: dict of name and values. Contains 2 item: resource type and
|
path: the resource path.
|
||||||
permission
|
properties: dict of name and values. Contains 2 item: resource type and
|
||||||
request_url: the url of the webresource include all the queries.
|
permission
|
||||||
'''
|
request_url: the url of the webresource include all the queries.
|
||||||
|
'''
|
||||||
def __init__(self, path=None, request_url=None, properties=None):
|
|
||||||
self.path = path
|
def __init__(self, path=None, request_url=None, properties=None):
|
||||||
self.properties = properties or {}
|
self.path = path
|
||||||
self.request_url = request_url
|
self.properties = properties or {}
|
||||||
|
self.request_url = request_url
|
||||||
|
|
||||||
class Permission(object):
|
|
||||||
|
class Permission(object):
|
||||||
'''
|
|
||||||
Permission class. Contains the path and query_string for the path.
|
'''
|
||||||
|
Permission class. Contains the path and query_string for the path.
|
||||||
path: the resource path
|
|
||||||
query_string: dict of name, values. Contains SIGNED_START, SIGNED_EXPIRY
|
path: the resource path
|
||||||
SIGNED_RESOURCE, SIGNED_PERMISSION, SIGNED_IDENTIFIER,
|
query_string: dict of name, values. Contains SIGNED_START, SIGNED_EXPIRY
|
||||||
SIGNED_SIGNATURE name values.
|
SIGNED_RESOURCE, SIGNED_PERMISSION, SIGNED_IDENTIFIER,
|
||||||
'''
|
SIGNED_SIGNATURE name values.
|
||||||
|
'''
|
||||||
def __init__(self, path=None, query_string=None):
|
|
||||||
self.path = path
|
def __init__(self, path=None, query_string=None):
|
||||||
self.query_string = query_string
|
self.path = path
|
||||||
|
self.query_string = query_string
|
||||||
|
|
||||||
class SharedAccessPolicy(object):
|
|
||||||
|
class SharedAccessPolicy(object):
|
||||||
''' SharedAccessPolicy class. '''
|
|
||||||
|
''' SharedAccessPolicy class. '''
|
||||||
def __init__(self, access_policy, signed_identifier=None):
|
|
||||||
self.id = signed_identifier
|
def __init__(self, access_policy, signed_identifier=None):
|
||||||
self.access_policy = access_policy
|
self.id = signed_identifier
|
||||||
|
self.access_policy = access_policy
|
||||||
|
|
||||||
class SharedAccessSignature(object):
|
|
||||||
|
class SharedAccessSignature(object):
|
||||||
'''
|
|
||||||
The main class used to do the signing and generating the signature.
|
'''
|
||||||
|
The main class used to do the signing and generating the signature.
|
||||||
account_name:
|
|
||||||
the storage account name used to generate shared access signature
|
account_name:
|
||||||
account_key: the access key to genenerate share access signature
|
the storage account name used to generate shared access signature
|
||||||
permission_set: the permission cache used to signed the request url.
|
account_key: the access key to genenerate share access signature
|
||||||
'''
|
permission_set: the permission cache used to signed the request url.
|
||||||
|
'''
|
||||||
def __init__(self, account_name, account_key, permission_set=None):
|
|
||||||
self.account_name = account_name
|
def __init__(self, account_name, account_key, permission_set=None):
|
||||||
self.account_key = account_key
|
self.account_name = account_name
|
||||||
self.permission_set = permission_set
|
self.account_key = account_key
|
||||||
|
self.permission_set = permission_set
|
||||||
def generate_signed_query_string(self, path, resource_type,
|
|
||||||
shared_access_policy,
|
def generate_signed_query_string(self, path, resource_type,
|
||||||
version=X_MS_VERSION):
|
shared_access_policy,
|
||||||
'''
|
version=X_MS_VERSION):
|
||||||
Generates the query string for path, resource type and shared access
|
'''
|
||||||
policy.
|
Generates the query string for path, resource type and shared access
|
||||||
|
policy.
|
||||||
path: the resource
|
|
||||||
resource_type: could be blob or container
|
path: the resource
|
||||||
shared_access_policy: shared access policy
|
resource_type: could be blob or container
|
||||||
version:
|
shared_access_policy: shared access policy
|
||||||
x-ms-version for storage service, or None to get a signed query
|
version:
|
||||||
string compatible with pre 2012-02-12 clients, where the version
|
x-ms-version for storage service, or None to get a signed query
|
||||||
is not included in the query string.
|
string compatible with pre 2012-02-12 clients, where the version
|
||||||
'''
|
is not included in the query string.
|
||||||
|
'''
|
||||||
query_string = {}
|
|
||||||
if shared_access_policy.access_policy.start:
|
query_string = {}
|
||||||
query_string[
|
if shared_access_policy.access_policy.start:
|
||||||
SIGNED_START] = shared_access_policy.access_policy.start
|
query_string[
|
||||||
|
SIGNED_START] = shared_access_policy.access_policy.start
|
||||||
if version:
|
|
||||||
query_string[SIGNED_VERSION] = version
|
if version:
|
||||||
query_string[SIGNED_EXPIRY] = shared_access_policy.access_policy.expiry
|
query_string[SIGNED_VERSION] = version
|
||||||
query_string[SIGNED_RESOURCE] = resource_type
|
query_string[SIGNED_EXPIRY] = shared_access_policy.access_policy.expiry
|
||||||
query_string[
|
query_string[SIGNED_RESOURCE] = resource_type
|
||||||
SIGNED_PERMISSION] = shared_access_policy.access_policy.permission
|
query_string[
|
||||||
|
SIGNED_PERMISSION] = shared_access_policy.access_policy.permission
|
||||||
if shared_access_policy.id:
|
|
||||||
query_string[SIGNED_IDENTIFIER] = shared_access_policy.id
|
if shared_access_policy.id:
|
||||||
|
query_string[SIGNED_IDENTIFIER] = shared_access_policy.id
|
||||||
query_string[SIGNED_SIGNATURE] = self._generate_signature(
|
|
||||||
path, shared_access_policy, version)
|
query_string[SIGNED_SIGNATURE] = self._generate_signature(
|
||||||
return query_string
|
path, shared_access_policy, version)
|
||||||
|
return query_string
|
||||||
def sign_request(self, web_resource):
|
|
||||||
''' sign request to generate request_url with sharedaccesssignature
|
def sign_request(self, web_resource):
|
||||||
info for web_resource.'''
|
''' sign request to generate request_url with sharedaccesssignature
|
||||||
|
info for web_resource.'''
|
||||||
if self.permission_set:
|
|
||||||
for shared_access_signature in self.permission_set:
|
if self.permission_set:
|
||||||
if self._permission_matches_request(
|
for shared_access_signature in self.permission_set:
|
||||||
shared_access_signature, web_resource,
|
if self._permission_matches_request(
|
||||||
web_resource.properties[
|
shared_access_signature, web_resource,
|
||||||
SIGNED_RESOURCE_TYPE],
|
web_resource.properties[
|
||||||
web_resource.properties[SHARED_ACCESS_PERMISSION]):
|
SIGNED_RESOURCE_TYPE],
|
||||||
if web_resource.request_url.find('?') == -1:
|
web_resource.properties[SHARED_ACCESS_PERMISSION]):
|
||||||
web_resource.request_url += '?'
|
if web_resource.request_url.find('?') == -1:
|
||||||
else:
|
web_resource.request_url += '?'
|
||||||
web_resource.request_url += '&'
|
else:
|
||||||
|
web_resource.request_url += '&'
|
||||||
web_resource.request_url += self._convert_query_string(
|
|
||||||
shared_access_signature.query_string)
|
web_resource.request_url += self._convert_query_string(
|
||||||
break
|
shared_access_signature.query_string)
|
||||||
return web_resource
|
break
|
||||||
|
return web_resource
|
||||||
def _convert_query_string(self, query_string):
|
|
||||||
''' Converts query string to str. The order of name, values is very
|
def _convert_query_string(self, query_string):
|
||||||
important and can't be wrong.'''
|
''' Converts query string to str. The order of name, values is very
|
||||||
|
important and can't be wrong.'''
|
||||||
convert_str = ''
|
|
||||||
if SIGNED_START in query_string:
|
convert_str = ''
|
||||||
convert_str += SIGNED_START + '=' + \
|
if SIGNED_START in query_string:
|
||||||
url_quote(query_string[SIGNED_START]) + '&'
|
convert_str += SIGNED_START + '=' + \
|
||||||
convert_str += SIGNED_EXPIRY + '=' + \
|
url_quote(query_string[SIGNED_START]) + '&'
|
||||||
url_quote(query_string[SIGNED_EXPIRY]) + '&'
|
convert_str += SIGNED_EXPIRY + '=' + \
|
||||||
convert_str += SIGNED_PERMISSION + '=' + \
|
url_quote(query_string[SIGNED_EXPIRY]) + '&'
|
||||||
query_string[SIGNED_PERMISSION] + '&'
|
convert_str += SIGNED_PERMISSION + '=' + \
|
||||||
convert_str += SIGNED_RESOURCE + '=' + \
|
query_string[SIGNED_PERMISSION] + '&'
|
||||||
query_string[SIGNED_RESOURCE] + '&'
|
convert_str += SIGNED_RESOURCE + '=' + \
|
||||||
|
query_string[SIGNED_RESOURCE] + '&'
|
||||||
if SIGNED_IDENTIFIER in query_string:
|
|
||||||
convert_str += SIGNED_IDENTIFIER + '=' + \
|
if SIGNED_IDENTIFIER in query_string:
|
||||||
query_string[SIGNED_IDENTIFIER] + '&'
|
convert_str += SIGNED_IDENTIFIER + '=' + \
|
||||||
if SIGNED_VERSION in query_string:
|
query_string[SIGNED_IDENTIFIER] + '&'
|
||||||
convert_str += SIGNED_VERSION + '=' + \
|
if SIGNED_VERSION in query_string:
|
||||||
query_string[SIGNED_VERSION] + '&'
|
convert_str += SIGNED_VERSION + '=' + \
|
||||||
convert_str += SIGNED_SIGNATURE + '=' + \
|
query_string[SIGNED_VERSION] + '&'
|
||||||
url_quote(query_string[SIGNED_SIGNATURE]) + '&'
|
convert_str += SIGNED_SIGNATURE + '=' + \
|
||||||
return convert_str
|
url_quote(query_string[SIGNED_SIGNATURE]) + '&'
|
||||||
|
return convert_str
|
||||||
def _generate_signature(self, path, shared_access_policy, version):
|
|
||||||
''' Generates signature for a given path and shared access policy. '''
|
def _generate_signature(self, path, shared_access_policy, version):
|
||||||
|
''' Generates signature for a given path and shared access policy. '''
|
||||||
def get_value_to_append(value, no_new_line=False):
|
|
||||||
return_value = ''
|
def get_value_to_append(value, no_new_line=False):
|
||||||
if value:
|
return_value = ''
|
||||||
return_value = value
|
if value:
|
||||||
if not no_new_line:
|
return_value = value
|
||||||
return_value += '\n'
|
if not no_new_line:
|
||||||
return return_value
|
return_value += '\n'
|
||||||
|
return return_value
|
||||||
if path[0] != '/':
|
|
||||||
path = '/' + path
|
if path[0] != '/':
|
||||||
|
path = '/' + path
|
||||||
canonicalized_resource = '/' + self.account_name + path
|
|
||||||
|
canonicalized_resource = '/' + self.account_name + path
|
||||||
# Form the string to sign from shared_access_policy and canonicalized
|
|
||||||
# resource. The order of values is important.
|
# Form the string to sign from shared_access_policy and canonicalized
|
||||||
string_to_sign = \
|
# resource. The order of values is important.
|
||||||
(get_value_to_append(shared_access_policy.access_policy.permission) +
|
string_to_sign = \
|
||||||
get_value_to_append(shared_access_policy.access_policy.start) +
|
(get_value_to_append(shared_access_policy.access_policy.permission) +
|
||||||
get_value_to_append(shared_access_policy.access_policy.expiry) +
|
get_value_to_append(shared_access_policy.access_policy.start) +
|
||||||
get_value_to_append(canonicalized_resource))
|
get_value_to_append(shared_access_policy.access_policy.expiry) +
|
||||||
|
get_value_to_append(canonicalized_resource))
|
||||||
if version:
|
|
||||||
string_to_sign += get_value_to_append(shared_access_policy.id)
|
if version:
|
||||||
string_to_sign += get_value_to_append(version, True)
|
string_to_sign += get_value_to_append(shared_access_policy.id)
|
||||||
else:
|
string_to_sign += get_value_to_append(version, True)
|
||||||
string_to_sign += get_value_to_append(shared_access_policy.id, True)
|
else:
|
||||||
|
string_to_sign += get_value_to_append(shared_access_policy.id, True)
|
||||||
return self._sign(string_to_sign)
|
|
||||||
|
return self._sign(string_to_sign)
|
||||||
def _permission_matches_request(self, shared_access_signature,
|
|
||||||
web_resource, resource_type,
|
def _permission_matches_request(self, shared_access_signature,
|
||||||
required_permission):
|
web_resource, resource_type,
|
||||||
''' Check whether requested permission matches given
|
required_permission):
|
||||||
shared_access_signature, web_resource and resource type. '''
|
''' Check whether requested permission matches given
|
||||||
|
shared_access_signature, web_resource and resource type. '''
|
||||||
required_resource_type = resource_type
|
|
||||||
if required_resource_type == RESOURCE_BLOB:
|
required_resource_type = resource_type
|
||||||
required_resource_type += RESOURCE_CONTAINER
|
if required_resource_type == RESOURCE_BLOB:
|
||||||
|
required_resource_type += RESOURCE_CONTAINER
|
||||||
for name, value in shared_access_signature.query_string.items():
|
|
||||||
if name == SIGNED_RESOURCE and \
|
for name, value in shared_access_signature.query_string.items():
|
||||||
required_resource_type.find(value) == -1:
|
if name == SIGNED_RESOURCE and \
|
||||||
return False
|
required_resource_type.find(value) == -1:
|
||||||
elif name == SIGNED_PERMISSION and \
|
return False
|
||||||
required_permission.find(value) == -1:
|
elif name == SIGNED_PERMISSION and \
|
||||||
return False
|
required_permission.find(value) == -1:
|
||||||
|
return False
|
||||||
return web_resource.path.find(shared_access_signature.path) != -1
|
|
||||||
|
return web_resource.path.find(shared_access_signature.path) != -1
|
||||||
def _sign(self, string_to_sign):
|
|
||||||
''' use HMAC-SHA256 to sign the string and convert it as base64
|
def _sign(self, string_to_sign):
|
||||||
encoded string. '''
|
''' use HMAC-SHA256 to sign the string and convert it as base64
|
||||||
|
encoded string. '''
|
||||||
return _sign_string(self.account_key, string_to_sign)
|
|
||||||
|
return _sign_string(self.account_key, string_to_sign)
|
||||||
|
|||||||
@@ -1,152 +1,152 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from azure import (
|
from azure import (
|
||||||
WindowsAzureError,
|
WindowsAzureError,
|
||||||
DEV_ACCOUNT_NAME,
|
DEV_ACCOUNT_NAME,
|
||||||
DEV_ACCOUNT_KEY,
|
DEV_ACCOUNT_KEY,
|
||||||
_ERROR_STORAGE_MISSING_INFO,
|
_ERROR_STORAGE_MISSING_INFO,
|
||||||
)
|
)
|
||||||
from azure.http import HTTPError
|
from azure.http import HTTPError
|
||||||
from azure.http.httpclient import _HTTPClient
|
from azure.http.httpclient import _HTTPClient
|
||||||
from azure.storage import _storage_error_handler
|
from azure.storage import _storage_error_handler
|
||||||
|
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
# constants for azure app setting environment variables
|
# constants for azure app setting environment variables
|
||||||
AZURE_STORAGE_ACCOUNT = 'AZURE_STORAGE_ACCOUNT'
|
AZURE_STORAGE_ACCOUNT = 'AZURE_STORAGE_ACCOUNT'
|
||||||
AZURE_STORAGE_ACCESS_KEY = 'AZURE_STORAGE_ACCESS_KEY'
|
AZURE_STORAGE_ACCESS_KEY = 'AZURE_STORAGE_ACCESS_KEY'
|
||||||
EMULATED = 'EMULATED'
|
EMULATED = 'EMULATED'
|
||||||
|
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class _StorageClient(object):
|
class _StorageClient(object):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
This is the base class for BlobManager, TableManager and QueueManager.
|
This is the base class for BlobManager, TableManager and QueueManager.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, account_name=None, account_key=None, protocol='https',
|
def __init__(self, account_name=None, account_key=None, protocol='https',
|
||||||
host_base='', dev_host=''):
|
host_base='', dev_host=''):
|
||||||
'''
|
'''
|
||||||
account_name: your storage account name, required for all operations.
|
account_name: your storage account name, required for all operations.
|
||||||
account_key: your storage account key, required for all operations.
|
account_key: your storage account key, required for all operations.
|
||||||
protocol: Optional. Protocol. Defaults to http.
|
protocol: Optional. Protocol. Defaults to http.
|
||||||
host_base:
|
host_base:
|
||||||
Optional. Live host base url. Defaults to Azure url. Override this
|
Optional. Live host base url. Defaults to Azure url. Override this
|
||||||
for on-premise.
|
for on-premise.
|
||||||
dev_host: Optional. Dev host url. Defaults to localhost.
|
dev_host: Optional. Dev host url. Defaults to localhost.
|
||||||
'''
|
'''
|
||||||
self.account_name = account_name
|
self.account_name = account_name
|
||||||
self.account_key = account_key
|
self.account_key = account_key
|
||||||
self.requestid = None
|
self.requestid = None
|
||||||
self.protocol = protocol
|
self.protocol = protocol
|
||||||
self.host_base = host_base
|
self.host_base = host_base
|
||||||
self.dev_host = dev_host
|
self.dev_host = dev_host
|
||||||
|
|
||||||
# the app is not run in azure emulator or use default development
|
# the app is not run in azure emulator or use default development
|
||||||
# storage account and key if app is run in emulator.
|
# storage account and key if app is run in emulator.
|
||||||
self.use_local_storage = False
|
self.use_local_storage = False
|
||||||
|
|
||||||
# check whether it is run in emulator.
|
# check whether it is run in emulator.
|
||||||
if EMULATED in os.environ:
|
if EMULATED in os.environ:
|
||||||
self.is_emulated = os.environ[EMULATED].lower() != 'false'
|
self.is_emulated = os.environ[EMULATED].lower() != 'false'
|
||||||
else:
|
else:
|
||||||
self.is_emulated = False
|
self.is_emulated = False
|
||||||
|
|
||||||
# get account_name and account key. If they are not set when
|
# get account_name and account key. If they are not set when
|
||||||
# constructing, get the account and key from environment variables if
|
# constructing, get the account and key from environment variables if
|
||||||
# the app is not run in azure emulator or use default development
|
# the app is not run in azure emulator or use default development
|
||||||
# storage account and key if app is run in emulator.
|
# storage account and key if app is run in emulator.
|
||||||
if not self.account_name or not self.account_key:
|
if not self.account_name or not self.account_key:
|
||||||
if self.is_emulated:
|
if self.is_emulated:
|
||||||
self.account_name = DEV_ACCOUNT_NAME
|
self.account_name = DEV_ACCOUNT_NAME
|
||||||
self.account_key = DEV_ACCOUNT_KEY
|
self.account_key = DEV_ACCOUNT_KEY
|
||||||
self.protocol = 'http'
|
self.protocol = 'http'
|
||||||
self.use_local_storage = True
|
self.use_local_storage = True
|
||||||
else:
|
else:
|
||||||
self.account_name = os.environ.get(AZURE_STORAGE_ACCOUNT)
|
self.account_name = os.environ.get(AZURE_STORAGE_ACCOUNT)
|
||||||
self.account_key = os.environ.get(AZURE_STORAGE_ACCESS_KEY)
|
self.account_key = os.environ.get(AZURE_STORAGE_ACCESS_KEY)
|
||||||
|
|
||||||
if not self.account_name or not self.account_key:
|
if not self.account_name or not self.account_key:
|
||||||
raise WindowsAzureError(_ERROR_STORAGE_MISSING_INFO)
|
raise WindowsAzureError(_ERROR_STORAGE_MISSING_INFO)
|
||||||
|
|
||||||
self._httpclient = _HTTPClient(
|
self._httpclient = _HTTPClient(
|
||||||
service_instance=self,
|
service_instance=self,
|
||||||
account_key=self.account_key,
|
account_key=self.account_key,
|
||||||
account_name=self.account_name,
|
account_name=self.account_name,
|
||||||
protocol=self.protocol)
|
protocol=self.protocol)
|
||||||
self._batchclient = None
|
self._batchclient = None
|
||||||
self._filter = self._perform_request_worker
|
self._filter = self._perform_request_worker
|
||||||
|
|
||||||
def with_filter(self, filter):
|
def with_filter(self, filter):
|
||||||
'''
|
'''
|
||||||
Returns a new service which will process requests with the specified
|
Returns a new service which will process requests with the specified
|
||||||
filter. Filtering operations can include logging, automatic retrying,
|
filter. Filtering operations can include logging, automatic retrying,
|
||||||
etc... The filter is a lambda which receives the HTTPRequest and
|
etc... The filter is a lambda which receives the HTTPRequest and
|
||||||
another lambda. The filter can perform any pre-processing on the
|
another lambda. The filter can perform any pre-processing on the
|
||||||
request, pass it off to the next lambda, and then perform any
|
request, pass it off to the next lambda, and then perform any
|
||||||
post-processing on the response.
|
post-processing on the response.
|
||||||
'''
|
'''
|
||||||
res = type(self)(self.account_name, self.account_key, self.protocol)
|
res = type(self)(self.account_name, self.account_key, self.protocol)
|
||||||
old_filter = self._filter
|
old_filter = self._filter
|
||||||
|
|
||||||
def new_filter(request):
|
def new_filter(request):
|
||||||
return filter(request, old_filter)
|
return filter(request, old_filter)
|
||||||
|
|
||||||
res._filter = new_filter
|
res._filter = new_filter
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def set_proxy(self, host, port, user=None, password=None):
|
def set_proxy(self, host, port, user=None, password=None):
|
||||||
'''
|
'''
|
||||||
Sets the proxy server host and port for the HTTP CONNECT Tunnelling.
|
Sets the proxy server host and port for the HTTP CONNECT Tunnelling.
|
||||||
|
|
||||||
host: Address of the proxy. Ex: '192.168.0.100'
|
host: Address of the proxy. Ex: '192.168.0.100'
|
||||||
port: Port of the proxy. Ex: 6000
|
port: Port of the proxy. Ex: 6000
|
||||||
user: User for proxy authorization.
|
user: User for proxy authorization.
|
||||||
password: Password for proxy authorization.
|
password: Password for proxy authorization.
|
||||||
'''
|
'''
|
||||||
self._httpclient.set_proxy(host, port, user, password)
|
self._httpclient.set_proxy(host, port, user, password)
|
||||||
|
|
||||||
def _get_host(self):
|
def _get_host(self):
|
||||||
if self.use_local_storage:
|
if self.use_local_storage:
|
||||||
return self.dev_host
|
return self.dev_host
|
||||||
else:
|
else:
|
||||||
return self.account_name + self.host_base
|
return self.account_name + self.host_base
|
||||||
|
|
||||||
def _perform_request_worker(self, request):
|
def _perform_request_worker(self, request):
|
||||||
return self._httpclient.perform_request(request)
|
return self._httpclient.perform_request(request)
|
||||||
|
|
||||||
def _perform_request(self, request, text_encoding='utf-8'):
|
def _perform_request(self, request, text_encoding='utf-8'):
|
||||||
'''
|
'''
|
||||||
Sends the request and return response. Catches HTTPError and hand it
|
Sends the request and return response. Catches HTTPError and hand it
|
||||||
to error handler
|
to error handler
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
if self._batchclient is not None:
|
if self._batchclient is not None:
|
||||||
return self._batchclient.insert_request_to_batch(request)
|
return self._batchclient.insert_request_to_batch(request)
|
||||||
else:
|
else:
|
||||||
resp = self._filter(request)
|
resp = self._filter(request)
|
||||||
|
|
||||||
if sys.version_info >= (3,) and isinstance(resp, bytes) and \
|
if sys.version_info >= (3,) and isinstance(resp, bytes) and \
|
||||||
text_encoding:
|
text_encoding:
|
||||||
resp = resp.decode(text_encoding)
|
resp = resp.decode(text_encoding)
|
||||||
|
|
||||||
except HTTPError as ex:
|
except HTTPError as ex:
|
||||||
_storage_error_handler(ex)
|
_storage_error_handler(ex)
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|||||||
@@ -1,491 +1,491 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Copyright (c) Microsoft. All rights reserved.
|
# Copyright (c) Microsoft. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
from azure import (
|
from azure import (
|
||||||
WindowsAzureError,
|
WindowsAzureError,
|
||||||
TABLE_SERVICE_HOST_BASE,
|
TABLE_SERVICE_HOST_BASE,
|
||||||
DEV_TABLE_HOST,
|
DEV_TABLE_HOST,
|
||||||
_convert_class_to_xml,
|
_convert_class_to_xml,
|
||||||
_convert_response_to_feeds,
|
_convert_response_to_feeds,
|
||||||
_dont_fail_not_exist,
|
_dont_fail_not_exist,
|
||||||
_dont_fail_on_exist,
|
_dont_fail_on_exist,
|
||||||
_get_request_body,
|
_get_request_body,
|
||||||
_int_or_none,
|
_int_or_none,
|
||||||
_parse_response,
|
_parse_response,
|
||||||
_parse_response_for_dict,
|
_parse_response_for_dict,
|
||||||
_parse_response_for_dict_filter,
|
_parse_response_for_dict_filter,
|
||||||
_str,
|
_str,
|
||||||
_str_or_none,
|
_str_or_none,
|
||||||
_update_request_uri_query_local_storage,
|
_update_request_uri_query_local_storage,
|
||||||
_validate_not_none,
|
_validate_not_none,
|
||||||
)
|
)
|
||||||
from azure.http import HTTPRequest
|
from azure.http import HTTPRequest
|
||||||
from azure.http.batchclient import _BatchClient
|
from azure.http.batchclient import _BatchClient
|
||||||
from azure.storage import (
|
from azure.storage import (
|
||||||
StorageServiceProperties,
|
StorageServiceProperties,
|
||||||
_convert_entity_to_xml,
|
_convert_entity_to_xml,
|
||||||
_convert_response_to_entity,
|
_convert_response_to_entity,
|
||||||
_convert_table_to_xml,
|
_convert_table_to_xml,
|
||||||
_convert_xml_to_entity,
|
_convert_xml_to_entity,
|
||||||
_convert_xml_to_table,
|
_convert_xml_to_table,
|
||||||
_sign_storage_table_request,
|
_sign_storage_table_request,
|
||||||
_update_storage_table_header,
|
_update_storage_table_header,
|
||||||
)
|
)
|
||||||
from azure.storage.storageclient import _StorageClient
|
from azure.storage.storageclient import _StorageClient
|
||||||
|
|
||||||
|
|
||||||
class TableService(_StorageClient):
|
class TableService(_StorageClient):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
This is the main class managing Table resources.
|
This is the main class managing Table resources.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, account_name=None, account_key=None, protocol='https',
|
def __init__(self, account_name=None, account_key=None, protocol='https',
|
||||||
host_base=TABLE_SERVICE_HOST_BASE, dev_host=DEV_TABLE_HOST):
|
host_base=TABLE_SERVICE_HOST_BASE, dev_host=DEV_TABLE_HOST):
|
||||||
'''
|
'''
|
||||||
account_name: your storage account name, required for all operations.
|
account_name: your storage account name, required for all operations.
|
||||||
account_key: your storage account key, required for all operations.
|
account_key: your storage account key, required for all operations.
|
||||||
protocol: Optional. Protocol. Defaults to http.
|
protocol: Optional. Protocol. Defaults to http.
|
||||||
host_base:
|
host_base:
|
||||||
Optional. Live host base url. Defaults to Azure url. Override this
|
Optional. Live host base url. Defaults to Azure url. Override this
|
||||||
for on-premise.
|
for on-premise.
|
||||||
dev_host: Optional. Dev host url. Defaults to localhost.
|
dev_host: Optional. Dev host url. Defaults to localhost.
|
||||||
'''
|
'''
|
||||||
super(TableService, self).__init__(
|
super(TableService, self).__init__(
|
||||||
account_name, account_key, protocol, host_base, dev_host)
|
account_name, account_key, protocol, host_base, dev_host)
|
||||||
|
|
||||||
def begin_batch(self):
|
def begin_batch(self):
|
||||||
if self._batchclient is None:
|
if self._batchclient is None:
|
||||||
self._batchclient = _BatchClient(
|
self._batchclient = _BatchClient(
|
||||||
service_instance=self,
|
service_instance=self,
|
||||||
account_key=self.account_key,
|
account_key=self.account_key,
|
||||||
account_name=self.account_name)
|
account_name=self.account_name)
|
||||||
return self._batchclient.begin_batch()
|
return self._batchclient.begin_batch()
|
||||||
|
|
||||||
def commit_batch(self):
|
def commit_batch(self):
|
||||||
try:
|
try:
|
||||||
ret = self._batchclient.commit_batch()
|
ret = self._batchclient.commit_batch()
|
||||||
finally:
|
finally:
|
||||||
self._batchclient = None
|
self._batchclient = None
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def cancel_batch(self):
|
def cancel_batch(self):
|
||||||
self._batchclient = None
|
self._batchclient = None
|
||||||
|
|
||||||
def get_table_service_properties(self):
|
def get_table_service_properties(self):
|
||||||
'''
|
'''
|
||||||
Gets the properties of a storage account's Table service, including
|
Gets the properties of a storage account's Table service, including
|
||||||
Windows Azure Storage Analytics.
|
Windows Azure Storage Analytics.
|
||||||
'''
|
'''
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/?restype=service&comp=properties'
|
request.path = '/?restype=service&comp=properties'
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response(response, StorageServiceProperties)
|
return _parse_response(response, StorageServiceProperties)
|
||||||
|
|
||||||
def set_table_service_properties(self, storage_service_properties):
|
def set_table_service_properties(self, storage_service_properties):
|
||||||
'''
|
'''
|
||||||
Sets the properties of a storage account's Table Service, including
|
Sets the properties of a storage account's Table Service, including
|
||||||
Windows Azure Storage Analytics.
|
Windows Azure Storage Analytics.
|
||||||
|
|
||||||
storage_service_properties: StorageServiceProperties object.
|
storage_service_properties: StorageServiceProperties object.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('storage_service_properties',
|
_validate_not_none('storage_service_properties',
|
||||||
storage_service_properties)
|
storage_service_properties)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'PUT'
|
request.method = 'PUT'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/?restype=service&comp=properties'
|
request.path = '/?restype=service&comp=properties'
|
||||||
request.body = _get_request_body(
|
request.body = _get_request_body(
|
||||||
_convert_class_to_xml(storage_service_properties))
|
_convert_class_to_xml(storage_service_properties))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response_for_dict(response)
|
return _parse_response_for_dict(response)
|
||||||
|
|
||||||
def query_tables(self, table_name=None, top=None, next_table_name=None):
|
def query_tables(self, table_name=None, top=None, next_table_name=None):
|
||||||
'''
|
'''
|
||||||
Returns a list of tables under the specified account.
|
Returns a list of tables under the specified account.
|
||||||
|
|
||||||
table_name: Optional. The specific table to query.
|
table_name: Optional. The specific table to query.
|
||||||
top: Optional. Maximum number of tables to return.
|
top: Optional. Maximum number of tables to return.
|
||||||
next_table_name:
|
next_table_name:
|
||||||
Optional. When top is used, the next table name is stored in
|
Optional. When top is used, the next table name is stored in
|
||||||
result.x_ms_continuation['NextTableName']
|
result.x_ms_continuation['NextTableName']
|
||||||
'''
|
'''
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
if table_name is not None:
|
if table_name is not None:
|
||||||
uri_part_table_name = "('" + table_name + "')"
|
uri_part_table_name = "('" + table_name + "')"
|
||||||
else:
|
else:
|
||||||
uri_part_table_name = ""
|
uri_part_table_name = ""
|
||||||
request.path = '/Tables' + uri_part_table_name + ''
|
request.path = '/Tables' + uri_part_table_name + ''
|
||||||
request.query = [
|
request.query = [
|
||||||
('$top', _int_or_none(top)),
|
('$top', _int_or_none(top)),
|
||||||
('NextTableName', _str_or_none(next_table_name))
|
('NextTableName', _str_or_none(next_table_name))
|
||||||
]
|
]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _convert_response_to_feeds(response, _convert_xml_to_table)
|
return _convert_response_to_feeds(response, _convert_xml_to_table)
|
||||||
|
|
||||||
def create_table(self, table, fail_on_exist=False):
|
def create_table(self, table, fail_on_exist=False):
|
||||||
'''
|
'''
|
||||||
Creates a new table in the storage account.
|
Creates a new table in the storage account.
|
||||||
|
|
||||||
table:
|
table:
|
||||||
Name of the table to create. Table name may contain only
|
Name of the table to create. Table name may contain only
|
||||||
alphanumeric characters and cannot begin with a numeric character.
|
alphanumeric characters and cannot begin with a numeric character.
|
||||||
It is case-insensitive and must be from 3 to 63 characters long.
|
It is case-insensitive and must be from 3 to 63 characters long.
|
||||||
fail_on_exist: Specify whether throw exception when table exists.
|
fail_on_exist: Specify whether throw exception when table exists.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table', table)
|
_validate_not_none('table', table)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/Tables'
|
request.path = '/Tables'
|
||||||
request.body = _get_request_body(_convert_table_to_xml(table))
|
request.body = _get_request_body(_convert_table_to_xml(table))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
if not fail_on_exist:
|
if not fail_on_exist:
|
||||||
try:
|
try:
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
return True
|
return True
|
||||||
except WindowsAzureError as ex:
|
except WindowsAzureError as ex:
|
||||||
_dont_fail_on_exist(ex)
|
_dont_fail_on_exist(ex)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def delete_table(self, table_name, fail_not_exist=False):
|
def delete_table(self, table_name, fail_not_exist=False):
|
||||||
'''
|
'''
|
||||||
table_name: Name of the table to delete.
|
table_name: Name of the table to delete.
|
||||||
fail_not_exist:
|
fail_not_exist:
|
||||||
Specify whether throw exception when table doesn't exist.
|
Specify whether throw exception when table doesn't exist.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/Tables(\'' + _str(table_name) + '\')'
|
request.path = '/Tables(\'' + _str(table_name) + '\')'
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
if not fail_not_exist:
|
if not fail_not_exist:
|
||||||
try:
|
try:
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
return True
|
return True
|
||||||
except WindowsAzureError as ex:
|
except WindowsAzureError as ex:
|
||||||
_dont_fail_not_exist(ex)
|
_dont_fail_not_exist(ex)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_entity(self, table_name, partition_key, row_key, select=''):
|
def get_entity(self, table_name, partition_key, row_key, select=''):
|
||||||
'''
|
'''
|
||||||
Get an entity in a table; includes the $select options.
|
Get an entity in a table; includes the $select options.
|
||||||
|
|
||||||
partition_key: PartitionKey of the entity.
|
partition_key: PartitionKey of the entity.
|
||||||
row_key: RowKey of the entity.
|
row_key: RowKey of the entity.
|
||||||
select: Property names to select.
|
select: Property names to select.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
_validate_not_none('partition_key', partition_key)
|
_validate_not_none('partition_key', partition_key)
|
||||||
_validate_not_none('row_key', row_key)
|
_validate_not_none('row_key', row_key)
|
||||||
_validate_not_none('select', select)
|
_validate_not_none('select', select)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(table_name) + \
|
request.path = '/' + _str(table_name) + \
|
||||||
'(PartitionKey=\'' + _str(partition_key) + \
|
'(PartitionKey=\'' + _str(partition_key) + \
|
||||||
'\',RowKey=\'' + \
|
'\',RowKey=\'' + \
|
||||||
_str(row_key) + '\')?$select=' + \
|
_str(row_key) + '\')?$select=' + \
|
||||||
_str(select) + ''
|
_str(select) + ''
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _convert_response_to_entity(response)
|
return _convert_response_to_entity(response)
|
||||||
|
|
||||||
def query_entities(self, table_name, filter=None, select=None, top=None,
|
def query_entities(self, table_name, filter=None, select=None, top=None,
|
||||||
next_partition_key=None, next_row_key=None):
|
next_partition_key=None, next_row_key=None):
|
||||||
'''
|
'''
|
||||||
Get entities in a table; includes the $filter and $select options.
|
Get entities in a table; includes the $filter and $select options.
|
||||||
|
|
||||||
table_name: Table to query.
|
table_name: Table to query.
|
||||||
filter:
|
filter:
|
||||||
Optional. Filter as described at
|
Optional. Filter as described at
|
||||||
http://msdn.microsoft.com/en-us/library/windowsazure/dd894031.aspx
|
http://msdn.microsoft.com/en-us/library/windowsazure/dd894031.aspx
|
||||||
select: Optional. Property names to select from the entities.
|
select: Optional. Property names to select from the entities.
|
||||||
top: Optional. Maximum number of entities to return.
|
top: Optional. Maximum number of entities to return.
|
||||||
next_partition_key:
|
next_partition_key:
|
||||||
Optional. When top is used, the next partition key is stored in
|
Optional. When top is used, the next partition key is stored in
|
||||||
result.x_ms_continuation['NextPartitionKey']
|
result.x_ms_continuation['NextPartitionKey']
|
||||||
next_row_key:
|
next_row_key:
|
||||||
Optional. When top is used, the next partition key is stored in
|
Optional. When top is used, the next partition key is stored in
|
||||||
result.x_ms_continuation['NextRowKey']
|
result.x_ms_continuation['NextRowKey']
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(table_name) + '()'
|
request.path = '/' + _str(table_name) + '()'
|
||||||
request.query = [
|
request.query = [
|
||||||
('$filter', _str_or_none(filter)),
|
('$filter', _str_or_none(filter)),
|
||||||
('$select', _str_or_none(select)),
|
('$select', _str_or_none(select)),
|
||||||
('$top', _int_or_none(top)),
|
('$top', _int_or_none(top)),
|
||||||
('NextPartitionKey', _str_or_none(next_partition_key)),
|
('NextPartitionKey', _str_or_none(next_partition_key)),
|
||||||
('NextRowKey', _str_or_none(next_row_key))
|
('NextRowKey', _str_or_none(next_row_key))
|
||||||
]
|
]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _convert_response_to_feeds(response, _convert_xml_to_entity)
|
return _convert_response_to_feeds(response, _convert_xml_to_entity)
|
||||||
|
|
||||||
def insert_entity(self, table_name, entity,
|
def insert_entity(self, table_name, entity,
|
||||||
content_type='application/atom+xml'):
|
content_type='application/atom+xml'):
|
||||||
'''
|
'''
|
||||||
Inserts a new entity into a table.
|
Inserts a new entity into a table.
|
||||||
|
|
||||||
table_name: Table name.
|
table_name: Table name.
|
||||||
entity:
|
entity:
|
||||||
Required. The entity object to insert. Could be a dict format or
|
Required. The entity object to insert. Could be a dict format or
|
||||||
entity object.
|
entity object.
|
||||||
content_type: Required. Must be set to application/atom+xml
|
content_type: Required. Must be set to application/atom+xml
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
_validate_not_none('entity', entity)
|
_validate_not_none('entity', entity)
|
||||||
_validate_not_none('content_type', content_type)
|
_validate_not_none('content_type', content_type)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(table_name) + ''
|
request.path = '/' + _str(table_name) + ''
|
||||||
request.headers = [('Content-Type', _str_or_none(content_type))]
|
request.headers = [('Content-Type', _str_or_none(content_type))]
|
||||||
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _convert_response_to_entity(response)
|
return _convert_response_to_entity(response)
|
||||||
|
|
||||||
def update_entity(self, table_name, partition_key, row_key, entity,
|
def update_entity(self, table_name, partition_key, row_key, entity,
|
||||||
content_type='application/atom+xml', if_match='*'):
|
content_type='application/atom+xml', if_match='*'):
|
||||||
'''
|
'''
|
||||||
Updates an existing entity in a table. The Update Entity operation
|
Updates an existing entity in a table. The Update Entity operation
|
||||||
replaces the entire entity and can be used to remove properties.
|
replaces the entire entity and can be used to remove properties.
|
||||||
|
|
||||||
table_name: Table name.
|
table_name: Table name.
|
||||||
partition_key: PartitionKey of the entity.
|
partition_key: PartitionKey of the entity.
|
||||||
row_key: RowKey of the entity.
|
row_key: RowKey of the entity.
|
||||||
entity:
|
entity:
|
||||||
Required. The entity object to insert. Could be a dict format or
|
Required. The entity object to insert. Could be a dict format or
|
||||||
entity object.
|
entity object.
|
||||||
content_type: Required. Must be set to application/atom+xml
|
content_type: Required. Must be set to application/atom+xml
|
||||||
if_match:
|
if_match:
|
||||||
Optional. Specifies the condition for which the merge should be
|
Optional. Specifies the condition for which the merge should be
|
||||||
performed. To force an unconditional merge, set to the wildcard
|
performed. To force an unconditional merge, set to the wildcard
|
||||||
character (*).
|
character (*).
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
_validate_not_none('partition_key', partition_key)
|
_validate_not_none('partition_key', partition_key)
|
||||||
_validate_not_none('row_key', row_key)
|
_validate_not_none('row_key', row_key)
|
||||||
_validate_not_none('entity', entity)
|
_validate_not_none('entity', entity)
|
||||||
_validate_not_none('content_type', content_type)
|
_validate_not_none('content_type', content_type)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'PUT'
|
request.method = 'PUT'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + \
|
request.path = '/' + \
|
||||||
_str(table_name) + '(PartitionKey=\'' + \
|
_str(table_name) + '(PartitionKey=\'' + \
|
||||||
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
||||||
request.headers = [
|
request.headers = [
|
||||||
('Content-Type', _str_or_none(content_type)),
|
('Content-Type', _str_or_none(content_type)),
|
||||||
('If-Match', _str_or_none(if_match))
|
('If-Match', _str_or_none(if_match))
|
||||||
]
|
]
|
||||||
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response_for_dict_filter(response, filter=['etag'])
|
return _parse_response_for_dict_filter(response, filter=['etag'])
|
||||||
|
|
||||||
def merge_entity(self, table_name, partition_key, row_key, entity,
|
def merge_entity(self, table_name, partition_key, row_key, entity,
|
||||||
content_type='application/atom+xml', if_match='*'):
|
content_type='application/atom+xml', if_match='*'):
|
||||||
'''
|
'''
|
||||||
Updates an existing entity by updating the entity's properties. This
|
Updates an existing entity by updating the entity's properties. This
|
||||||
operation does not replace the existing entity as the Update Entity
|
operation does not replace the existing entity as the Update Entity
|
||||||
operation does.
|
operation does.
|
||||||
|
|
||||||
table_name: Table name.
|
table_name: Table name.
|
||||||
partition_key: PartitionKey of the entity.
|
partition_key: PartitionKey of the entity.
|
||||||
row_key: RowKey of the entity.
|
row_key: RowKey of the entity.
|
||||||
entity:
|
entity:
|
||||||
Required. The entity object to insert. Can be a dict format or
|
Required. The entity object to insert. Can be a dict format or
|
||||||
entity object.
|
entity object.
|
||||||
content_type: Required. Must be set to application/atom+xml
|
content_type: Required. Must be set to application/atom+xml
|
||||||
if_match:
|
if_match:
|
||||||
Optional. Specifies the condition for which the merge should be
|
Optional. Specifies the condition for which the merge should be
|
||||||
performed. To force an unconditional merge, set to the wildcard
|
performed. To force an unconditional merge, set to the wildcard
|
||||||
character (*).
|
character (*).
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
_validate_not_none('partition_key', partition_key)
|
_validate_not_none('partition_key', partition_key)
|
||||||
_validate_not_none('row_key', row_key)
|
_validate_not_none('row_key', row_key)
|
||||||
_validate_not_none('entity', entity)
|
_validate_not_none('entity', entity)
|
||||||
_validate_not_none('content_type', content_type)
|
_validate_not_none('content_type', content_type)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'MERGE'
|
request.method = 'MERGE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + \
|
request.path = '/' + \
|
||||||
_str(table_name) + '(PartitionKey=\'' + \
|
_str(table_name) + '(PartitionKey=\'' + \
|
||||||
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
||||||
request.headers = [
|
request.headers = [
|
||||||
('Content-Type', _str_or_none(content_type)),
|
('Content-Type', _str_or_none(content_type)),
|
||||||
('If-Match', _str_or_none(if_match))
|
('If-Match', _str_or_none(if_match))
|
||||||
]
|
]
|
||||||
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response_for_dict_filter(response, filter=['etag'])
|
return _parse_response_for_dict_filter(response, filter=['etag'])
|
||||||
|
|
||||||
def delete_entity(self, table_name, partition_key, row_key,
|
def delete_entity(self, table_name, partition_key, row_key,
|
||||||
content_type='application/atom+xml', if_match='*'):
|
content_type='application/atom+xml', if_match='*'):
|
||||||
'''
|
'''
|
||||||
Deletes an existing entity in a table.
|
Deletes an existing entity in a table.
|
||||||
|
|
||||||
table_name: Table name.
|
table_name: Table name.
|
||||||
partition_key: PartitionKey of the entity.
|
partition_key: PartitionKey of the entity.
|
||||||
row_key: RowKey of the entity.
|
row_key: RowKey of the entity.
|
||||||
content_type: Required. Must be set to application/atom+xml
|
content_type: Required. Must be set to application/atom+xml
|
||||||
if_match:
|
if_match:
|
||||||
Optional. Specifies the condition for which the delete should be
|
Optional. Specifies the condition for which the delete should be
|
||||||
performed. To force an unconditional delete, set to the wildcard
|
performed. To force an unconditional delete, set to the wildcard
|
||||||
character (*).
|
character (*).
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
_validate_not_none('partition_key', partition_key)
|
_validate_not_none('partition_key', partition_key)
|
||||||
_validate_not_none('row_key', row_key)
|
_validate_not_none('row_key', row_key)
|
||||||
_validate_not_none('content_type', content_type)
|
_validate_not_none('content_type', content_type)
|
||||||
_validate_not_none('if_match', if_match)
|
_validate_not_none('if_match', if_match)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + \
|
request.path = '/' + \
|
||||||
_str(table_name) + '(PartitionKey=\'' + \
|
_str(table_name) + '(PartitionKey=\'' + \
|
||||||
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
||||||
request.headers = [
|
request.headers = [
|
||||||
('Content-Type', _str_or_none(content_type)),
|
('Content-Type', _str_or_none(content_type)),
|
||||||
('If-Match', _str_or_none(if_match))
|
('If-Match', _str_or_none(if_match))
|
||||||
]
|
]
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
|
|
||||||
def insert_or_replace_entity(self, table_name, partition_key, row_key,
|
def insert_or_replace_entity(self, table_name, partition_key, row_key,
|
||||||
entity, content_type='application/atom+xml'):
|
entity, content_type='application/atom+xml'):
|
||||||
'''
|
'''
|
||||||
Replaces an existing entity or inserts a new entity if it does not
|
Replaces an existing entity or inserts a new entity if it does not
|
||||||
exist in the table. Because this operation can insert or update an
|
exist in the table. Because this operation can insert or update an
|
||||||
entity, it is also known as an "upsert" operation.
|
entity, it is also known as an "upsert" operation.
|
||||||
|
|
||||||
table_name: Table name.
|
table_name: Table name.
|
||||||
partition_key: PartitionKey of the entity.
|
partition_key: PartitionKey of the entity.
|
||||||
row_key: RowKey of the entity.
|
row_key: RowKey of the entity.
|
||||||
entity:
|
entity:
|
||||||
Required. The entity object to insert. Could be a dict format or
|
Required. The entity object to insert. Could be a dict format or
|
||||||
entity object.
|
entity object.
|
||||||
content_type: Required. Must be set to application/atom+xml
|
content_type: Required. Must be set to application/atom+xml
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
_validate_not_none('partition_key', partition_key)
|
_validate_not_none('partition_key', partition_key)
|
||||||
_validate_not_none('row_key', row_key)
|
_validate_not_none('row_key', row_key)
|
||||||
_validate_not_none('entity', entity)
|
_validate_not_none('entity', entity)
|
||||||
_validate_not_none('content_type', content_type)
|
_validate_not_none('content_type', content_type)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'PUT'
|
request.method = 'PUT'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + \
|
request.path = '/' + \
|
||||||
_str(table_name) + '(PartitionKey=\'' + \
|
_str(table_name) + '(PartitionKey=\'' + \
|
||||||
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
||||||
request.headers = [('Content-Type', _str_or_none(content_type))]
|
request.headers = [('Content-Type', _str_or_none(content_type))]
|
||||||
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response_for_dict_filter(response, filter=['etag'])
|
return _parse_response_for_dict_filter(response, filter=['etag'])
|
||||||
|
|
||||||
def insert_or_merge_entity(self, table_name, partition_key, row_key,
|
def insert_or_merge_entity(self, table_name, partition_key, row_key,
|
||||||
entity, content_type='application/atom+xml'):
|
entity, content_type='application/atom+xml'):
|
||||||
'''
|
'''
|
||||||
Merges an existing entity or inserts a new entity if it does not exist
|
Merges an existing entity or inserts a new entity if it does not exist
|
||||||
in the table. Because this operation can insert or update an entity,
|
in the table. Because this operation can insert or update an entity,
|
||||||
it is also known as an "upsert" operation.
|
it is also known as an "upsert" operation.
|
||||||
|
|
||||||
table_name: Table name.
|
table_name: Table name.
|
||||||
partition_key: PartitionKey of the entity.
|
partition_key: PartitionKey of the entity.
|
||||||
row_key: RowKey of the entity.
|
row_key: RowKey of the entity.
|
||||||
entity:
|
entity:
|
||||||
Required. The entity object to insert. Could be a dict format or
|
Required. The entity object to insert. Could be a dict format or
|
||||||
entity object.
|
entity object.
|
||||||
content_type: Required. Must be set to application/atom+xml
|
content_type: Required. Must be set to application/atom+xml
|
||||||
'''
|
'''
|
||||||
_validate_not_none('table_name', table_name)
|
_validate_not_none('table_name', table_name)
|
||||||
_validate_not_none('partition_key', partition_key)
|
_validate_not_none('partition_key', partition_key)
|
||||||
_validate_not_none('row_key', row_key)
|
_validate_not_none('row_key', row_key)
|
||||||
_validate_not_none('entity', entity)
|
_validate_not_none('entity', entity)
|
||||||
_validate_not_none('content_type', content_type)
|
_validate_not_none('content_type', content_type)
|
||||||
request = HTTPRequest()
|
request = HTTPRequest()
|
||||||
request.method = 'MERGE'
|
request.method = 'MERGE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + \
|
request.path = '/' + \
|
||||||
_str(table_name) + '(PartitionKey=\'' + \
|
_str(table_name) + '(PartitionKey=\'' + \
|
||||||
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
_str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')'
|
||||||
request.headers = [('Content-Type', _str_or_none(content_type))]
|
request.headers = [('Content-Type', _str_or_none(content_type))]
|
||||||
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
request.body = _get_request_body(_convert_entity_to_xml(entity))
|
||||||
request.path, request.query = _update_request_uri_query_local_storage(
|
request.path, request.query = _update_request_uri_query_local_storage(
|
||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_table_header(request)
|
request.headers = _update_storage_table_header(request)
|
||||||
response = self._perform_request(request)
|
response = self._perform_request(request)
|
||||||
|
|
||||||
return _parse_response_for_dict_filter(response, filter=['etag'])
|
return _parse_response_for_dict_filter(response, filter=['etag'])
|
||||||
|
|
||||||
def _perform_request_worker(self, request):
|
def _perform_request_worker(self, request):
|
||||||
auth = _sign_storage_table_request(request,
|
auth = _sign_storage_table_request(request,
|
||||||
self.account_name,
|
self.account_name,
|
||||||
self.account_key)
|
self.account_key)
|
||||||
request.headers.append(('Authorization', auth))
|
request.headers.append(('Authorization', auth))
|
||||||
return self._httpclient.perform_request(request)
|
return self._httpclient.perform_request(request)
|
||||||
|
|||||||
Reference in New Issue
Block a user