mirror of
https://github.com/ansible/awx.git
synced 2026-05-16 05:47:38 -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,
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
import ast
|
import ast
|
||||||
import base64
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
import warnings
|
import warnings
|
||||||
@@ -34,7 +36,7 @@ from xml.sax.saxutils import escape as xml_escape
|
|||||||
# constants
|
# constants
|
||||||
|
|
||||||
__author__ = 'Microsoft Corp. <ptvshelp@microsoft.com>'
|
__author__ = 'Microsoft Corp. <ptvshelp@microsoft.com>'
|
||||||
__version__ = '0.8.1'
|
__version__ = '0.9.0'
|
||||||
|
|
||||||
# Live ServiceClient URLs
|
# Live ServiceClient URLs
|
||||||
BLOB_SERVICE_HOST_BASE = '.blob.core.windows.net'
|
BLOB_SERVICE_HOST_BASE = '.blob.core.windows.net'
|
||||||
@@ -103,10 +105,9 @@ class WindowsAzureData(object):
|
|||||||
It is only used to check whether it is instance or not. '''
|
It is only used to check whether it is instance or not. '''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class WindowsAzureError(Exception):
|
class WindowsAzureError(Exception):
|
||||||
|
|
||||||
''' WindowsAzure Excpetion base class. '''
|
''' WindowsAzure Exception base class. '''
|
||||||
|
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
super(WindowsAzureError, self).__init__(message)
|
super(WindowsAzureError, self).__init__(message)
|
||||||
@@ -188,25 +189,38 @@ def _get_readable_id(id_name, id_prefix_to_skip):
|
|||||||
return id_name
|
return id_name
|
||||||
|
|
||||||
|
|
||||||
|
def _get_entry_properties_from_node(entry, include_id, id_prefix_to_skip=None, use_title_as_id=False):
|
||||||
|
''' get properties from entry xml '''
|
||||||
|
properties = {}
|
||||||
|
|
||||||
|
etag = entry.getAttributeNS(METADATA_NS, 'etag')
|
||||||
|
if etag:
|
||||||
|
properties['etag'] = etag
|
||||||
|
for updated in _get_child_nodes(entry, 'updated'):
|
||||||
|
properties['updated'] = updated.firstChild.nodeValue
|
||||||
|
for name in _get_children_from_path(entry, 'author', 'name'):
|
||||||
|
if name.firstChild is not None:
|
||||||
|
properties['author'] = name.firstChild.nodeValue
|
||||||
|
|
||||||
|
if include_id:
|
||||||
|
if use_title_as_id:
|
||||||
|
for title in _get_child_nodes(entry, 'title'):
|
||||||
|
properties['name'] = title.firstChild.nodeValue
|
||||||
|
else:
|
||||||
|
for id in _get_child_nodes(entry, 'id'):
|
||||||
|
properties['name'] = _get_readable_id(
|
||||||
|
id.firstChild.nodeValue, id_prefix_to_skip)
|
||||||
|
|
||||||
|
return properties
|
||||||
|
|
||||||
|
|
||||||
def _get_entry_properties(xmlstr, include_id, id_prefix_to_skip=None):
|
def _get_entry_properties(xmlstr, include_id, id_prefix_to_skip=None):
|
||||||
''' get properties from entry xml '''
|
''' get properties from entry xml '''
|
||||||
xmldoc = minidom.parseString(xmlstr)
|
xmldoc = minidom.parseString(xmlstr)
|
||||||
properties = {}
|
properties = {}
|
||||||
|
|
||||||
for entry in _get_child_nodes(xmldoc, 'entry'):
|
for entry in _get_child_nodes(xmldoc, 'entry'):
|
||||||
etag = entry.getAttributeNS(METADATA_NS, 'etag')
|
properties.update(_get_entry_properties_from_node(entry, include_id, id_prefix_to_skip))
|
||||||
if etag:
|
|
||||||
properties['etag'] = etag
|
|
||||||
for updated in _get_child_nodes(entry, 'updated'):
|
|
||||||
properties['updated'] = updated.firstChild.nodeValue
|
|
||||||
for name in _get_children_from_path(entry, 'author', 'name'):
|
|
||||||
if name.firstChild is not None:
|
|
||||||
properties['author'] = name.firstChild.nodeValue
|
|
||||||
|
|
||||||
if include_id:
|
|
||||||
for id in _get_child_nodes(entry, 'id'):
|
|
||||||
properties['name'] = _get_readable_id(
|
|
||||||
id.firstChild.nodeValue, id_prefix_to_skip)
|
|
||||||
|
|
||||||
return properties
|
return properties
|
||||||
|
|
||||||
@@ -284,6 +298,18 @@ _KNOWN_SERIALIZATION_XFORMS = {
|
|||||||
'os': 'OS',
|
'os': 'OS',
|
||||||
'persistent_vm_downtime_info': 'PersistentVMDowntimeInfo',
|
'persistent_vm_downtime_info': 'PersistentVMDowntimeInfo',
|
||||||
'copy_id': 'CopyId',
|
'copy_id': 'CopyId',
|
||||||
|
'os_state': 'OSState',
|
||||||
|
'vm_image': 'VMImage',
|
||||||
|
'vm_images': 'VMImages',
|
||||||
|
'os_disk_configuration': 'OSDiskConfiguration',
|
||||||
|
'public_ips': 'PublicIPs',
|
||||||
|
'public_ip': 'PublicIP',
|
||||||
|
'supported_os': 'SupportedOS',
|
||||||
|
'reserved_ip': 'ReservedIP',
|
||||||
|
'reserved_ips': 'ReservedIPs',
|
||||||
|
'aad_tenant_id': 'AADTenantID',
|
||||||
|
'start_ip_address': 'StartIPAddress',
|
||||||
|
'end_ip_address': 'EndIPAddress',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -428,6 +454,25 @@ def _convert_response_to_feeds(response, convert_func):
|
|||||||
return feeds
|
return feeds
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_xml_to_windows_azure_object(xmlstr, azure_type, include_id=True, use_title_as_id=True):
|
||||||
|
xmldoc = minidom.parseString(xmlstr)
|
||||||
|
return_obj = azure_type()
|
||||||
|
xml_name = azure_type._xml_name if hasattr(azure_type, '_xml_name') else azure_type.__name__
|
||||||
|
|
||||||
|
# Only one entry here
|
||||||
|
for xml_entry in _get_children_from_path(xmldoc,
|
||||||
|
'entry'):
|
||||||
|
for node in _get_children_from_path(xml_entry,
|
||||||
|
'content',
|
||||||
|
xml_name):
|
||||||
|
_fill_data_to_return_object(node, return_obj)
|
||||||
|
for name, value in _get_entry_properties_from_node(xml_entry,
|
||||||
|
include_id=include_id,
|
||||||
|
use_title_as_id=use_title_as_id).items():
|
||||||
|
setattr(return_obj, name, value)
|
||||||
|
return return_obj
|
||||||
|
|
||||||
|
|
||||||
def _validate_type_bytes(param_name, param):
|
def _validate_type_bytes(param_name, param):
|
||||||
if not isinstance(param, bytes):
|
if not isinstance(param, bytes):
|
||||||
raise TypeError(_ERROR_VALUE_SHOULD_BE_BYTES.format(param_name))
|
raise TypeError(_ERROR_VALUE_SHOULD_BE_BYTES.format(param_name))
|
||||||
@@ -675,6 +720,13 @@ def _parse_response(response, return_type):
|
|||||||
'''
|
'''
|
||||||
return _parse_response_body_from_xml_text(response.body, return_type)
|
return _parse_response_body_from_xml_text(response.body, return_type)
|
||||||
|
|
||||||
|
def _parse_service_resources_response(response, return_type):
|
||||||
|
'''
|
||||||
|
Parse the HTTPResponse's body and fill all the data into a class of
|
||||||
|
return_type.
|
||||||
|
'''
|
||||||
|
return _parse_response_body_from_service_resources_xml_text(response.body, return_type)
|
||||||
|
|
||||||
|
|
||||||
def _fill_data_to_return_object(node, return_obj):
|
def _fill_data_to_return_object(node, return_obj):
|
||||||
members = dict(vars(return_obj))
|
members = dict(vars(return_obj))
|
||||||
@@ -700,6 +752,12 @@ def _fill_data_to_return_object(node, return_obj):
|
|||||||
value.pair_xml_element_name,
|
value.pair_xml_element_name,
|
||||||
value.key_xml_element_name,
|
value.key_xml_element_name,
|
||||||
value.value_xml_element_name))
|
value.value_xml_element_name))
|
||||||
|
elif isinstance(value, _xml_attribute):
|
||||||
|
real_value = None
|
||||||
|
if node.hasAttribute(value.xml_element_name):
|
||||||
|
real_value = node.getAttribute(value.xml_element_name)
|
||||||
|
if real_value is not None:
|
||||||
|
setattr(return_obj, name, real_value)
|
||||||
elif isinstance(value, WindowsAzureData):
|
elif isinstance(value, WindowsAzureData):
|
||||||
setattr(return_obj,
|
setattr(return_obj,
|
||||||
name,
|
name,
|
||||||
@@ -737,11 +795,24 @@ def _parse_response_body_from_xml_text(respbody, return_type):
|
|||||||
'''
|
'''
|
||||||
doc = minidom.parseString(respbody)
|
doc = minidom.parseString(respbody)
|
||||||
return_obj = return_type()
|
return_obj = return_type()
|
||||||
for node in _get_child_nodes(doc, return_type.__name__):
|
xml_name = return_type._xml_name if hasattr(return_type, '_xml_name') else return_type.__name__
|
||||||
|
for node in _get_child_nodes(doc, xml_name):
|
||||||
_fill_data_to_return_object(node, return_obj)
|
_fill_data_to_return_object(node, return_obj)
|
||||||
|
|
||||||
return return_obj
|
return return_obj
|
||||||
|
|
||||||
|
def _parse_response_body_from_service_resources_xml_text(respbody, return_type):
|
||||||
|
'''
|
||||||
|
parse the xml and fill all the data into a class of return_type
|
||||||
|
'''
|
||||||
|
doc = minidom.parseString(respbody)
|
||||||
|
return_obj = _list_of(return_type)
|
||||||
|
for node in _get_children_from_path(doc, "ServiceResources", "ServiceResource"):
|
||||||
|
local_obj = return_type()
|
||||||
|
_fill_data_to_return_object(node, local_obj)
|
||||||
|
return_obj.append(local_obj)
|
||||||
|
|
||||||
|
return return_obj
|
||||||
|
|
||||||
class _dict_of(dict):
|
class _dict_of(dict):
|
||||||
|
|
||||||
@@ -781,6 +852,15 @@ class _scalar_list_of(list):
|
|||||||
self.xml_element_name = xml_element_name
|
self.xml_element_name = xml_element_name
|
||||||
super(_scalar_list_of, self).__init__()
|
super(_scalar_list_of, self).__init__()
|
||||||
|
|
||||||
|
class _xml_attribute:
|
||||||
|
|
||||||
|
"""a accessor to XML attributes
|
||||||
|
expected to go in it along with its xml element name.
|
||||||
|
Used for deserialization and construction"""
|
||||||
|
|
||||||
|
def __init__(self, xml_element_name):
|
||||||
|
self.xml_element_name = xml_element_name
|
||||||
|
|
||||||
|
|
||||||
def _update_request_uri_query_local_storage(request, use_local_storage):
|
def _update_request_uri_query_local_storage(request, use_local_storage):
|
||||||
''' create correct uri and query for the request '''
|
''' create correct uri and query for the request '''
|
||||||
@@ -903,3 +983,17 @@ def _parse_response_for_dict_filter(response, filter):
|
|||||||
return return_dict
|
return return_dict
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _sign_string(key, string_to_sign, key_is_base64=True):
|
||||||
|
if key_is_base64:
|
||||||
|
key = _decode_base64_to_bytes(key)
|
||||||
|
else:
|
||||||
|
if isinstance(key, _unicode_type):
|
||||||
|
key = key.encode('utf-8')
|
||||||
|
if isinstance(string_to_sign, _unicode_type):
|
||||||
|
string_to_sign = string_to_sign.encode('utf-8')
|
||||||
|
signed_hmac_sha256 = hmac.HMAC(key, string_to_sign, hashlib.sha256)
|
||||||
|
digest = signed_hmac_sha256.digest()
|
||||||
|
encoded_digest = _encode_base64(digest)
|
||||||
|
return encoded_digest
|
||||||
|
|||||||
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>
|
||||||
@@ -36,6 +36,8 @@ else:
|
|||||||
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
|
||||||
|
DEBUG_RESPONSES = False
|
||||||
|
|
||||||
class _HTTPClient(object):
|
class _HTTPClient(object):
|
||||||
|
|
||||||
@@ -44,8 +46,7 @@ class _HTTPClient(object):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, service_instance, cert_file=None, account_name=None,
|
def __init__(self, service_instance, cert_file=None, account_name=None,
|
||||||
account_key=None, service_namespace=None, issuer=None,
|
account_key=None, protocol='https', request_session=None):
|
||||||
protocol='https'):
|
|
||||||
'''
|
'''
|
||||||
service_instance: service client instance.
|
service_instance: service client instance.
|
||||||
cert_file:
|
cert_file:
|
||||||
@@ -53,10 +54,9 @@ class _HTTPClient(object):
|
|||||||
service management.
|
service management.
|
||||||
account_name: the storage account.
|
account_name: the storage account.
|
||||||
account_key:
|
account_key:
|
||||||
the storage account access key for storage services or servicebus
|
the storage account access key.
|
||||||
access key for service bus service.
|
request_session:
|
||||||
service_namespace: the service namespace for service bus.
|
session object created with requests library (or compatible).
|
||||||
issuer: the issuer for service bus service.
|
|
||||||
'''
|
'''
|
||||||
self.service_instance = service_instance
|
self.service_instance = service_instance
|
||||||
self.status = None
|
self.status = None
|
||||||
@@ -65,14 +65,16 @@ class _HTTPClient(object):
|
|||||||
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.issuer = issuer
|
|
||||||
self.protocol = protocol
|
self.protocol = protocol
|
||||||
self.proxy_host = None
|
self.proxy_host = None
|
||||||
self.proxy_port = None
|
self.proxy_port = None
|
||||||
self.proxy_user = None
|
self.proxy_user = None
|
||||||
self.proxy_password = None
|
self.proxy_password = None
|
||||||
self.use_httplib = self.should_use_httplib()
|
self.request_session = request_session
|
||||||
|
if request_session:
|
||||||
|
self.use_httplib = True
|
||||||
|
else:
|
||||||
|
self.use_httplib = self.should_use_httplib()
|
||||||
|
|
||||||
def should_use_httplib(self):
|
def should_use_httplib(self):
|
||||||
if sys.platform.lower().startswith('win') and self.cert_file:
|
if sys.platform.lower().startswith('win') and self.cert_file:
|
||||||
@@ -111,6 +113,13 @@ class _HTTPClient(object):
|
|||||||
self.proxy_user = user
|
self.proxy_user = user
|
||||||
self.proxy_password = password
|
self.proxy_password = password
|
||||||
|
|
||||||
|
def get_uri(self, request):
|
||||||
|
''' Return the target uri for the request.'''
|
||||||
|
protocol = request.protocol_override \
|
||||||
|
if request.protocol_override else self.protocol
|
||||||
|
port = HTTP_PORT if protocol == 'http' else HTTPS_PORT
|
||||||
|
return protocol + '://' + request.host + ':' + str(port) + request.path
|
||||||
|
|
||||||
def get_connection(self, request):
|
def get_connection(self, request):
|
||||||
''' Create connection for the request. '''
|
''' Create connection for the request. '''
|
||||||
protocol = request.protocol_override \
|
protocol = request.protocol_override \
|
||||||
@@ -118,7 +127,12 @@ class _HTTPClient(object):
|
|||||||
target_host = request.host
|
target_host = request.host
|
||||||
target_port = HTTP_PORT if protocol == 'http' else HTTPS_PORT
|
target_port = HTTP_PORT if protocol == 'http' else HTTPS_PORT
|
||||||
|
|
||||||
if not self.use_httplib:
|
if self.request_session:
|
||||||
|
import azure.http.requestsclient
|
||||||
|
connection = azure.http.requestsclient._RequestsConnection(
|
||||||
|
target_host, protocol, self.request_session)
|
||||||
|
#TODO: proxy stuff
|
||||||
|
elif not self.use_httplib:
|
||||||
import azure.http.winhttp
|
import azure.http.winhttp
|
||||||
connection = azure.http.winhttp._HTTPConnection(
|
connection = azure.http.winhttp._HTTPConnection(
|
||||||
target_host, cert_file=self.cert_file, protocol=protocol)
|
target_host, cert_file=self.cert_file, protocol=protocol)
|
||||||
@@ -191,6 +205,13 @@ class _HTTPClient(object):
|
|||||||
self.send_request_headers(connection, request.headers)
|
self.send_request_headers(connection, request.headers)
|
||||||
self.send_request_body(connection, request.body)
|
self.send_request_body(connection, request.body)
|
||||||
|
|
||||||
|
if DEBUG_REQUESTS and request.body:
|
||||||
|
print('request:')
|
||||||
|
try:
|
||||||
|
print(request.body)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
resp = connection.getresponse()
|
resp = connection.getresponse()
|
||||||
self.status = int(resp.status)
|
self.status = int(resp.status)
|
||||||
self.message = resp.reason
|
self.message = resp.reason
|
||||||
@@ -206,6 +227,13 @@ class _HTTPClient(object):
|
|||||||
elif resp.length > 0:
|
elif resp.length > 0:
|
||||||
respbody = resp.read(resp.length)
|
respbody = resp.read(resp.length)
|
||||||
|
|
||||||
|
if DEBUG_RESPONSES and respbody:
|
||||||
|
print('response:')
|
||||||
|
try:
|
||||||
|
print(respbody)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
response = HTTPResponse(
|
response = HTTPResponse(
|
||||||
int(resp.status), resp.reason, headers, respbody)
|
int(resp.status), resp.reason, headers, respbody)
|
||||||
if self.status == 307:
|
if self.status == 307:
|
||||||
|
|||||||
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)
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
import ast
|
import ast
|
||||||
|
import json
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -167,16 +168,16 @@ class Message(WindowsAzureData):
|
|||||||
# extracts the topic and subscriptions name if it is topic message.
|
# extracts the topic and subscriptions name if it is topic message.
|
||||||
if location:
|
if location:
|
||||||
if '/subscriptions/' in location:
|
if '/subscriptions/' in location:
|
||||||
pos = location.find('/subscriptions/')
|
pos = location.find(service_bus_service.host_base.lower())+1
|
||||||
pos1 = location.rfind('/', 0, pos - 1)
|
pos1 = location.find('/subscriptions/')
|
||||||
self._topic_name = location[pos1 + 1:pos]
|
self._topic_name = location[pos+len(service_bus_service.host_base):pos1]
|
||||||
pos += len('/subscriptions/')
|
pos = pos1 + len('/subscriptions/')
|
||||||
pos1 = location.find('/', pos)
|
pos1 = location.find('/', pos)
|
||||||
self._subscription_name = location[pos:pos1]
|
self._subscription_name = location[pos:pos1]
|
||||||
elif '/messages/' in location:
|
elif '/messages/' in location:
|
||||||
pos = location.find('/messages/')
|
pos = location.find(service_bus_service.host_base.lower())+1
|
||||||
pos1 = location.rfind('/', 0, pos - 1)
|
pos1 = location.find('/messages/')
|
||||||
self._queue_name = location[pos1 + 1:pos]
|
self._queue_name = location[pos+len(service_bus_service.host_base):pos1]
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
''' Deletes itself if find queue name or topic name and subscription
|
''' Deletes itself if find queue name or topic name and subscription
|
||||||
@@ -255,7 +256,7 @@ def _create_message(response, service_instance):
|
|||||||
# gets all information from respheaders.
|
# gets all information from respheaders.
|
||||||
for name, value in response.headers:
|
for name, value in response.headers:
|
||||||
if name.lower() == 'brokerproperties':
|
if name.lower() == 'brokerproperties':
|
||||||
broker_properties = ast.literal_eval(value)
|
broker_properties = json.loads(value)
|
||||||
elif name.lower() == 'content-type':
|
elif name.lower() == 'content-type':
|
||||||
message_type = value
|
message_type = value
|
||||||
elif name.lower() == 'location':
|
elif name.lower() == 'location':
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
# 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 datetime
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -21,10 +22,13 @@ from azure import (
|
|||||||
_convert_response_to_feeds,
|
_convert_response_to_feeds,
|
||||||
_dont_fail_not_exist,
|
_dont_fail_not_exist,
|
||||||
_dont_fail_on_exist,
|
_dont_fail_on_exist,
|
||||||
|
_encode_base64,
|
||||||
_get_request_body,
|
_get_request_body,
|
||||||
_get_request_body_bytes_only,
|
_get_request_body_bytes_only,
|
||||||
_int_or_none,
|
_int_or_none,
|
||||||
|
_sign_string,
|
||||||
_str,
|
_str,
|
||||||
|
_unicode_type,
|
||||||
_update_request_uri_query,
|
_update_request_uri_query,
|
||||||
url_quote,
|
url_quote,
|
||||||
url_unquote,
|
url_unquote,
|
||||||
@@ -55,44 +59,94 @@ from azure.servicebus import (
|
|||||||
_service_bus_error_handler,
|
_service_bus_error_handler,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Token cache for Authentication
|
|
||||||
# Shared by the different instances of ServiceBusService
|
|
||||||
_tokens = {}
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceBusService(object):
|
class ServiceBusService(object):
|
||||||
|
|
||||||
def __init__(self, service_namespace=None, account_key=None, issuer=None,
|
def __init__(self, service_namespace=None, account_key=None, issuer=None,
|
||||||
x_ms_version='2011-06-01', host_base=SERVICE_BUS_HOST_BASE):
|
x_ms_version='2011-06-01', host_base=SERVICE_BUS_HOST_BASE,
|
||||||
# x_ms_version is not used, but the parameter is kept for backwards
|
shared_access_key_name=None, shared_access_key_value=None,
|
||||||
# compatibility
|
authentication=None):
|
||||||
|
'''
|
||||||
|
Initializes the service bus service for a namespace with the specified
|
||||||
|
authentication settings (SAS or ACS).
|
||||||
|
|
||||||
|
service_namespace:
|
||||||
|
Service bus namespace, required for all operations. If None,
|
||||||
|
the value is set to the AZURE_SERVICEBUS_NAMESPACE env variable.
|
||||||
|
account_key:
|
||||||
|
ACS authentication account key. If None, the value is set to the
|
||||||
|
AZURE_SERVICEBUS_ACCESS_KEY env variable.
|
||||||
|
Note that if both SAS and ACS settings are specified, SAS is used.
|
||||||
|
issuer:
|
||||||
|
ACS authentication issuer. If None, the value is set to the
|
||||||
|
AZURE_SERVICEBUS_ISSUER env variable.
|
||||||
|
Note that if both SAS and ACS settings are specified, SAS is used.
|
||||||
|
x_ms_version: Unused. Kept for backwards compatibility.
|
||||||
|
host_base:
|
||||||
|
Optional. Live host base url. Defaults to Azure url. Override this
|
||||||
|
for on-premise.
|
||||||
|
shared_access_key_name:
|
||||||
|
SAS authentication key name.
|
||||||
|
Note that if both SAS and ACS settings are specified, SAS is used.
|
||||||
|
shared_access_key_value:
|
||||||
|
SAS authentication key value.
|
||||||
|
Note that if both SAS and ACS settings are specified, SAS is used.
|
||||||
|
authentication:
|
||||||
|
Instance of authentication class. If this is specified, then
|
||||||
|
ACS and SAS parameters are ignored.
|
||||||
|
'''
|
||||||
self.requestid = None
|
self.requestid = None
|
||||||
self.service_namespace = service_namespace
|
self.service_namespace = service_namespace
|
||||||
self.account_key = account_key
|
|
||||||
self.issuer = issuer
|
|
||||||
self.host_base = host_base
|
self.host_base = host_base
|
||||||
|
|
||||||
# Get service namespace, account key and issuer.
|
|
||||||
# If they are set when constructing, then use them, else find them
|
|
||||||
# from environment variables.
|
|
||||||
if not self.service_namespace:
|
if not self.service_namespace:
|
||||||
self.service_namespace = os.environ.get(AZURE_SERVICEBUS_NAMESPACE)
|
self.service_namespace = os.environ.get(AZURE_SERVICEBUS_NAMESPACE)
|
||||||
if not self.account_key:
|
|
||||||
self.account_key = os.environ.get(AZURE_SERVICEBUS_ACCESS_KEY)
|
|
||||||
if not self.issuer:
|
|
||||||
self.issuer = os.environ.get(AZURE_SERVICEBUS_ISSUER)
|
|
||||||
|
|
||||||
if not self.service_namespace or \
|
if not self.service_namespace:
|
||||||
not self.account_key or not self.issuer:
|
raise WindowsAzureError('You need to provide servicebus namespace')
|
||||||
raise WindowsAzureError(
|
|
||||||
'You need to provide servicebus namespace, access key and Issuer')
|
|
||||||
|
|
||||||
self._httpclient = _HTTPClient(service_instance=self,
|
if authentication:
|
||||||
service_namespace=self.service_namespace,
|
self.authentication = authentication
|
||||||
account_key=self.account_key,
|
else:
|
||||||
issuer=self.issuer)
|
if not account_key:
|
||||||
|
account_key = os.environ.get(AZURE_SERVICEBUS_ACCESS_KEY)
|
||||||
|
if not issuer:
|
||||||
|
issuer = os.environ.get(AZURE_SERVICEBUS_ISSUER)
|
||||||
|
|
||||||
|
if shared_access_key_name and shared_access_key_value:
|
||||||
|
self.authentication = ServiceBusSASAuthentication(
|
||||||
|
shared_access_key_name,
|
||||||
|
shared_access_key_value)
|
||||||
|
elif account_key and issuer:
|
||||||
|
self.authentication = ServiceBusWrapTokenAuthentication(
|
||||||
|
account_key,
|
||||||
|
issuer)
|
||||||
|
else:
|
||||||
|
raise WindowsAzureError(
|
||||||
|
'You need to provide servicebus access key and Issuer OR shared access key and value')
|
||||||
|
|
||||||
|
self._httpclient = _HTTPClient(service_instance=self)
|
||||||
self._filter = self._httpclient.perform_request
|
self._filter = self._httpclient.perform_request
|
||||||
|
|
||||||
|
# Backwards compatibility:
|
||||||
|
# account_key and issuer used to be stored on the service class, they are
|
||||||
|
# now stored on the authentication class.
|
||||||
|
@property
|
||||||
|
def account_key(self):
|
||||||
|
return self.authentication.account_key
|
||||||
|
|
||||||
|
@account_key.setter
|
||||||
|
def account_key(self, value):
|
||||||
|
self.authentication.account_key = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issuer(self):
|
||||||
|
return self.authentication.issuer
|
||||||
|
|
||||||
|
@issuer.setter
|
||||||
|
def issuer(self, value):
|
||||||
|
self.authentication.issuer = value
|
||||||
|
|
||||||
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
|
||||||
@@ -102,8 +156,10 @@ class ServiceBusService(object):
|
|||||||
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 = ServiceBusService(self.service_namespace, self.account_key,
|
res = ServiceBusService(
|
||||||
self.issuer)
|
service_namespace=self.service_namespace,
|
||||||
|
authentication=self.authentication)
|
||||||
|
|
||||||
old_filter = self._filter
|
old_filter = self._filter
|
||||||
|
|
||||||
def new_filter(request):
|
def new_filter(request):
|
||||||
@@ -855,17 +911,30 @@ class ServiceBusService(object):
|
|||||||
('Content-Type',
|
('Content-Type',
|
||||||
'application/atom+xml;type=entry;charset=utf-8'))
|
'application/atom+xml;type=entry;charset=utf-8'))
|
||||||
|
|
||||||
# Adds authoriaztion header for authentication.
|
# Adds authorization header for authentication.
|
||||||
request.headers.append(
|
self.authentication.sign_request(request, self._httpclient)
|
||||||
('Authorization', self._sign_service_bus_request(request)))
|
|
||||||
|
|
||||||
return request.headers
|
return request.headers
|
||||||
|
|
||||||
def _sign_service_bus_request(self, request):
|
|
||||||
''' return the signed string with token. '''
|
|
||||||
|
|
||||||
|
# Token cache for Authentication
|
||||||
|
# Shared by the different instances of ServiceBusWrapTokenAuthentication
|
||||||
|
_tokens = {}
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceBusWrapTokenAuthentication:
|
||||||
|
def __init__(self, account_key, issuer):
|
||||||
|
self.account_key = account_key
|
||||||
|
self.issuer = issuer
|
||||||
|
|
||||||
|
def sign_request(self, request, httpclient):
|
||||||
|
request.headers.append(
|
||||||
|
('Authorization', self._get_authorization(request, httpclient)))
|
||||||
|
|
||||||
|
def _get_authorization(self, request, httpclient):
|
||||||
|
''' return the signed string with token. '''
|
||||||
return 'WRAP access_token="' + \
|
return 'WRAP access_token="' + \
|
||||||
self._get_token(request.host, request.path) + '"'
|
self._get_token(request.host, request.path, httpclient) + '"'
|
||||||
|
|
||||||
def _token_is_expired(self, token):
|
def _token_is_expired(self, token):
|
||||||
''' Check if token expires or not. '''
|
''' Check if token expires or not. '''
|
||||||
@@ -878,7 +947,7 @@ class ServiceBusService(object):
|
|||||||
# token to server.
|
# token to server.
|
||||||
return (token_expire_time - time_now) < 30
|
return (token_expire_time - time_now) < 30
|
||||||
|
|
||||||
def _get_token(self, host, path):
|
def _get_token(self, host, path, httpclient):
|
||||||
'''
|
'''
|
||||||
Returns token for the request.
|
Returns token for the request.
|
||||||
|
|
||||||
@@ -905,10 +974,38 @@ class ServiceBusService(object):
|
|||||||
'&wrap_scope=' +
|
'&wrap_scope=' +
|
||||||
url_quote('http://' + host + path)).encode('utf-8')
|
url_quote('http://' + host + path)).encode('utf-8')
|
||||||
request.headers.append(('Content-Length', str(len(request.body))))
|
request.headers.append(('Content-Length', str(len(request.body))))
|
||||||
resp = self._httpclient.perform_request(request)
|
resp = httpclient.perform_request(request)
|
||||||
|
|
||||||
token = resp.body.decode('utf-8')
|
token = resp.body.decode('utf-8')
|
||||||
token = url_unquote(token[token.find('=') + 1:token.rfind('&')])
|
token = url_unquote(token[token.find('=') + 1:token.rfind('&')])
|
||||||
_tokens[wrap_scope] = token
|
_tokens[wrap_scope] = token
|
||||||
|
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceBusSASAuthentication:
|
||||||
|
def __init__(self, key_name, key_value):
|
||||||
|
self.key_name = key_name
|
||||||
|
self.key_value = key_value
|
||||||
|
|
||||||
|
def sign_request(self, request, httpclient):
|
||||||
|
request.headers.append(
|
||||||
|
('Authorization', self._get_authorization(request, httpclient)))
|
||||||
|
|
||||||
|
def _get_authorization(self, request, httpclient):
|
||||||
|
uri = httpclient.get_uri(request)
|
||||||
|
uri = url_quote(uri, '').lower()
|
||||||
|
expiry = str(self._get_expiry())
|
||||||
|
|
||||||
|
to_sign = uri + '\n' + expiry
|
||||||
|
signature = url_quote(_sign_string(self.key_value, to_sign, False), '')
|
||||||
|
|
||||||
|
auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}'
|
||||||
|
auth = auth_format.format(signature, expiry, self.key_name, uri)
|
||||||
|
|
||||||
|
return auth
|
||||||
|
|
||||||
|
def _get_expiry(self):
|
||||||
|
'''Returns the UTC datetime, in seconds since Epoch, when this signed
|
||||||
|
request expires (5 minutes from now).'''
|
||||||
|
return int(round(time.time() + 300))
|
||||||
|
|||||||
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)
|
||||||
|
|
||||||
@@ -17,23 +17,56 @@ from azure import (
|
|||||||
_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 (
|
from azure.servicemanagement import (
|
||||||
_ServiceBusManagementXmlSerializer,
|
_ServiceBusManagementXmlSerializer,
|
||||||
)
|
QueueDescription,
|
||||||
|
TopicDescription,
|
||||||
|
NotificationHubDescription,
|
||||||
|
RelayDescription,
|
||||||
|
MetricProperties,
|
||||||
|
MetricValues,
|
||||||
|
MetricRollups,
|
||||||
|
)
|
||||||
from azure.servicemanagement.servicemanagementclient import (
|
from azure.servicemanagement.servicemanagementclient import (
|
||||||
_ServiceManagementClient,
|
_ServiceManagementClient,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
X_MS_VERSION = '2012-03-01'
|
||||||
|
|
||||||
class ServiceBusManagementService(_ServiceManagementClient):
|
class ServiceBusManagementService(_ServiceManagementClient):
|
||||||
|
|
||||||
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):
|
||||||
super(ServiceBusManagementService, self).__init__(
|
'''
|
||||||
subscription_id, cert_file, host)
|
Initializes the service bus management service.
|
||||||
|
|
||||||
#--Operations for service bus ----------------------------------------
|
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(ServiceBusManagementService, self).__init__(
|
||||||
|
subscription_id, cert_file, host, request_session)
|
||||||
|
self.x_ms_version = X_MS_VERSION
|
||||||
|
|
||||||
|
# Operations for service bus ----------------------------------------
|
||||||
def get_regions(self):
|
def get_regions(self):
|
||||||
'''
|
'''
|
||||||
Get list of available service bus regions.
|
Get list of available service bus regions.
|
||||||
@@ -111,3 +144,391 @@ class ServiceBusManagementService(_ServiceManagementClient):
|
|||||||
|
|
||||||
return _ServiceBusManagementXmlSerializer.xml_to_namespace_availability(
|
return _ServiceBusManagementXmlSerializer.xml_to_namespace_availability(
|
||||||
response.body)
|
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',
|
||||||
|
])
|
||||||
|
|||||||
@@ -31,21 +31,24 @@ 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
|
||||||
|
self.x_ms_version = X_MS_VERSION
|
||||||
|
self.content_type = 'application/atom+xml;type=entry;charset=utf-8'
|
||||||
|
|
||||||
if not self.cert_file:
|
if not self.cert_file and not request_session:
|
||||||
if AZURE_MANAGEMENT_CERTFILE in os.environ:
|
if AZURE_MANAGEMENT_CERTFILE in os.environ:
|
||||||
self.cert_file = os.environ[AZURE_MANAGEMENT_CERTFILE]
|
self.cert_file = os.environ[AZURE_MANAGEMENT_CERTFILE]
|
||||||
|
|
||||||
@@ -54,12 +57,14 @@ class _ServiceManagementClient(object):
|
|||||||
self.subscription_id = os.environ[
|
self.subscription_id = os.environ[
|
||||||
AZURE_MANAGEMENT_SUBSCRIPTIONID]
|
AZURE_MANAGEMENT_SUBSCRIPTIONID]
|
||||||
|
|
||||||
if not self.cert_file or not self.subscription_id:
|
if not self.request_session:
|
||||||
raise WindowsAzureError(
|
if not self.cert_file or not self.subscription_id:
|
||||||
'You need to provide subscription id and certificate file')
|
raise WindowsAzureError(
|
||||||
|
'You need to provide subscription id and certificate file')
|
||||||
|
|
||||||
self._httpclient = _HTTPClient(
|
self._httpclient = _HTTPClient(
|
||||||
service_instance=self, cert_file=self.cert_file)
|
service_instance=self, cert_file=self.cert_file,
|
||||||
|
request_session=self.request_session)
|
||||||
self._filter = self._httpclient.perform_request
|
self._filter = self._httpclient.perform_request
|
||||||
|
|
||||||
def with_filter(self, filter):
|
def with_filter(self, filter):
|
||||||
@@ -69,7 +74,8 @@ class _ServiceManagementClient(object):
|
|||||||
and another lambda. The filter can perform any pre-processing on the
|
and 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.subscription_id, self.cert_file, self.host)
|
res = type(self)(self.subscription_id, self.cert_file, self.host,
|
||||||
|
self.request_session)
|
||||||
old_filter = self._filter
|
old_filter = self._filter
|
||||||
|
|
||||||
def new_filter(request):
|
def new_filter(request):
|
||||||
@@ -89,6 +95,96 @@ class _ServiceManagementClient(object):
|
|||||||
'''
|
'''
|
||||||
self._httpclient.set_proxy(host, port, user, password)
|
self._httpclient.set_proxy(host, port, user, password)
|
||||||
|
|
||||||
|
def perform_get(self, path, x_ms_version=None):
|
||||||
|
'''
|
||||||
|
Performs a GET 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 = 'GET'
|
||||||
|
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
|
||||||
|
|
||||||
|
def perform_put(self, path, body, x_ms_version=None):
|
||||||
|
'''
|
||||||
|
Performs a PUT request and returns the response.
|
||||||
|
|
||||||
|
path:
|
||||||
|
Path to the resource.
|
||||||
|
Ex: '/<subscription-id>/services/hostedservices/<service-name>'
|
||||||
|
body:
|
||||||
|
Body for the PUT request.
|
||||||
|
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 = 'PUT'
|
||||||
|
request.host = self.host
|
||||||
|
request.path = path
|
||||||
|
request.body = _get_request_body(body)
|
||||||
|
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
|
||||||
|
|
||||||
|
def perform_post(self, path, body, x_ms_version=None):
|
||||||
|
'''
|
||||||
|
Performs a POST request and returns the response.
|
||||||
|
|
||||||
|
path:
|
||||||
|
Path to the resource.
|
||||||
|
Ex: '/<subscription-id>/services/hostedservices/<service-name>'
|
||||||
|
body:
|
||||||
|
Body for the POST request.
|
||||||
|
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 = 'POST'
|
||||||
|
request.host = self.host
|
||||||
|
request.path = path
|
||||||
|
request.body = _get_request_body(body)
|
||||||
|
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
|
||||||
|
|
||||||
|
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 --------------------------------------------------
|
#--Helper functions --------------------------------------------------
|
||||||
def _perform_request(self, request):
|
def _perform_request(self, request):
|
||||||
try:
|
try:
|
||||||
@@ -98,64 +194,60 @@ class _ServiceManagementClient(object):
|
|||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
def _perform_get(self, path, response_type):
|
def _update_management_header(self, request, x_ms_version):
|
||||||
request = HTTPRequest()
|
''' Add additional headers for management. '''
|
||||||
request.method = 'GET'
|
|
||||||
request.host = self.host
|
if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']:
|
||||||
request.path = path
|
request.headers.append(('Content-Length', str(len(request.body))))
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
|
||||||
request.headers = _update_management_header(request)
|
# append additional headers base on the service
|
||||||
response = self._perform_request(request)
|
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:
|
if response_type is not None:
|
||||||
return _parse_response(response, response_type)
|
return _parse_response(response, response_type)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _perform_put(self, path, body, async=False):
|
def _perform_put(self, path, body, async=False, x_ms_version=None):
|
||||||
request = HTTPRequest()
|
response = self.perform_put(path, body, x_ms_version)
|
||||||
request.method = 'PUT'
|
|
||||||
request.host = self.host
|
|
||||||
request.path = path
|
|
||||||
request.body = _get_request_body(body)
|
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
|
||||||
request.headers = _update_management_header(request)
|
|
||||||
response = self._perform_request(request)
|
|
||||||
|
|
||||||
if async:
|
if async:
|
||||||
return _parse_response_for_async_op(response)
|
return parse_response_for_async_op(response)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _perform_post(self, path, body, response_type=None, async=False):
|
def _perform_post(self, path, body, response_type=None, async=False,
|
||||||
request = HTTPRequest()
|
x_ms_version=None):
|
||||||
request.method = 'POST'
|
response = self.perform_post(path, body, x_ms_version)
|
||||||
request.host = self.host
|
|
||||||
request.path = path
|
|
||||||
request.body = _get_request_body(body)
|
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
|
||||||
request.headers = _update_management_header(request)
|
|
||||||
response = self._perform_request(request)
|
|
||||||
|
|
||||||
if response_type is not None:
|
if response_type is not None:
|
||||||
return _parse_response(response, response_type)
|
return _parse_response(response, response_type)
|
||||||
|
|
||||||
if async:
|
if async:
|
||||||
return _parse_response_for_async_op(response)
|
return parse_response_for_async_op(response)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _perform_delete(self, path, async=False):
|
def _perform_delete(self, path, async=False, x_ms_version=None):
|
||||||
request = HTTPRequest()
|
response = self.perform_delete(path, x_ms_version)
|
||||||
request.method = 'DELETE'
|
|
||||||
request.host = self.host
|
|
||||||
request.path = path
|
|
||||||
request.path, request.query = _update_request_uri_query(request)
|
|
||||||
request.headers = _update_management_header(request)
|
|
||||||
response = self._perform_request(request)
|
|
||||||
|
|
||||||
if async:
|
if async:
|
||||||
return _parse_response_for_async_op(response)
|
return parse_response_for_async_op(response)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -37,12 +37,19 @@ from azure.servicemanagement import (
|
|||||||
OperatingSystemFamilies,
|
OperatingSystemFamilies,
|
||||||
OSImage,
|
OSImage,
|
||||||
PersistentVMRole,
|
PersistentVMRole,
|
||||||
|
ResourceExtensions,
|
||||||
|
ReservedIP,
|
||||||
|
ReservedIPs,
|
||||||
|
RoleSize,
|
||||||
|
RoleSizes,
|
||||||
StorageService,
|
StorageService,
|
||||||
StorageServices,
|
StorageServices,
|
||||||
Subscription,
|
Subscription,
|
||||||
|
Subscriptions,
|
||||||
SubscriptionCertificate,
|
SubscriptionCertificate,
|
||||||
SubscriptionCertificates,
|
SubscriptionCertificates,
|
||||||
VirtualNetworkSites,
|
VirtualNetworkSites,
|
||||||
|
VMImages,
|
||||||
_XmlSerializer,
|
_XmlSerializer,
|
||||||
)
|
)
|
||||||
from azure.servicemanagement.servicemanagementclient import (
|
from azure.servicemanagement.servicemanagementclient import (
|
||||||
@@ -52,9 +59,49 @@ from azure.servicemanagement.servicemanagementclient import (
|
|||||||
class ServiceManagementService(_ServiceManagementClient):
|
class ServiceManagementService(_ServiceManagementClient):
|
||||||
|
|
||||||
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):
|
||||||
|
'''
|
||||||
|
Initializes the 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(ServiceManagementService, self).__init__(
|
super(ServiceManagementService, self).__init__(
|
||||||
subscription_id, cert_file, host)
|
subscription_id, cert_file, host, request_session)
|
||||||
|
|
||||||
|
#--Operations for subscriptions --------------------------------------
|
||||||
|
def list_role_sizes(self):
|
||||||
|
'''
|
||||||
|
Lists the role sizes that are available under the specified
|
||||||
|
subscription.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_role_sizes_path(),
|
||||||
|
RoleSizes)
|
||||||
|
|
||||||
|
def list_subscriptions(self):
|
||||||
|
'''
|
||||||
|
Returns a list of subscriptions that you can access.
|
||||||
|
|
||||||
|
You must make sure that the request that is made to the management
|
||||||
|
service is secure using an Active Directory access token.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_subscriptions_path(),
|
||||||
|
Subscriptions)
|
||||||
|
|
||||||
#--Operations for storage accounts -----------------------------------
|
#--Operations for storage accounts -----------------------------------
|
||||||
def list_storage_accounts(self):
|
def list_storage_accounts(self):
|
||||||
@@ -107,8 +154,9 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
|
|
||||||
def create_storage_account(self, service_name, description, label,
|
def create_storage_account(self, service_name, description, label,
|
||||||
affinity_group=None, location=None,
|
affinity_group=None, location=None,
|
||||||
geo_replication_enabled=True,
|
geo_replication_enabled=None,
|
||||||
extended_properties=None):
|
extended_properties=None,
|
||||||
|
account_type='Standard_GRS'):
|
||||||
'''
|
'''
|
||||||
Creates a new storage account in Windows Azure.
|
Creates a new storage account in Windows Azure.
|
||||||
|
|
||||||
@@ -131,12 +179,7 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
The location where the storage account is created. You can specify
|
The location where the storage account is created. You can specify
|
||||||
either a location or affinity_group, but not both.
|
either a location or affinity_group, but not both.
|
||||||
geo_replication_enabled:
|
geo_replication_enabled:
|
||||||
Specifies whether the storage account is created with the
|
Deprecated. Replaced by the account_type parameter.
|
||||||
geo-replication enabled. If the element is not included in the
|
|
||||||
request body, the default value is true. If set to true, the data
|
|
||||||
in the storage account is replicated across more than one
|
|
||||||
geographic location so as to enable resilience in the face of
|
|
||||||
catastrophic service loss.
|
|
||||||
extended_properties:
|
extended_properties:
|
||||||
Dictionary containing name/value pairs of storage account
|
Dictionary containing name/value pairs of storage account
|
||||||
properties. You can have a maximum of 50 extended property
|
properties. You can have a maximum of 50 extended property
|
||||||
@@ -144,6 +187,12 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
characters, only alphanumeric characters and underscores are valid
|
characters, only alphanumeric characters and underscores are valid
|
||||||
in the Name, and the name must start with a letter. The value has
|
in the Name, and the name must start with a letter. The value has
|
||||||
a maximum length of 255 characters.
|
a maximum length of 255 characters.
|
||||||
|
account_type:
|
||||||
|
Specifies whether the account supports locally-redundant storage,
|
||||||
|
geo-redundant storage, zone-redundant storage, or read access
|
||||||
|
geo-redundant storage.
|
||||||
|
Possible values are:
|
||||||
|
Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS
|
||||||
'''
|
'''
|
||||||
_validate_not_none('service_name', service_name)
|
_validate_not_none('service_name', service_name)
|
||||||
_validate_not_none('description', description)
|
_validate_not_none('description', description)
|
||||||
@@ -154,6 +203,8 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
if affinity_group is not None and location is not None:
|
if affinity_group is not None and location is not None:
|
||||||
raise WindowsAzureError(
|
raise WindowsAzureError(
|
||||||
'Only one of location or affinity_group needs to be specified')
|
'Only one of location or affinity_group needs to be specified')
|
||||||
|
if geo_replication_enabled == False:
|
||||||
|
account_type = 'Standard_LRS'
|
||||||
return self._perform_post(
|
return self._perform_post(
|
||||||
self._get_storage_service_path(),
|
self._get_storage_service_path(),
|
||||||
_XmlSerializer.create_storage_service_input_to_xml(
|
_XmlSerializer.create_storage_service_input_to_xml(
|
||||||
@@ -162,13 +213,14 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
label,
|
label,
|
||||||
affinity_group,
|
affinity_group,
|
||||||
location,
|
location,
|
||||||
geo_replication_enabled,
|
account_type,
|
||||||
extended_properties),
|
extended_properties),
|
||||||
async=True)
|
async=True)
|
||||||
|
|
||||||
def update_storage_account(self, service_name, description=None,
|
def update_storage_account(self, service_name, description=None,
|
||||||
label=None, geo_replication_enabled=None,
|
label=None, geo_replication_enabled=None,
|
||||||
extended_properties=None):
|
extended_properties=None,
|
||||||
|
account_type='Standard_GRS'):
|
||||||
'''
|
'''
|
||||||
Updates the label, the description, and enables or disables the
|
Updates the label, the description, and enables or disables the
|
||||||
geo-replication status for a storage account in Windows Azure.
|
geo-replication status for a storage account in Windows Azure.
|
||||||
@@ -182,12 +234,7 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
characters in length. The name can be used to identify the storage
|
characters in length. The name can be used to identify the storage
|
||||||
account for your tracking purposes.
|
account for your tracking purposes.
|
||||||
geo_replication_enabled:
|
geo_replication_enabled:
|
||||||
Specifies whether the storage account is created with the
|
Deprecated. Replaced by the account_type parameter.
|
||||||
geo-replication enabled. If the element is not included in the
|
|
||||||
request body, the default value is true. If set to true, the data
|
|
||||||
in the storage account is replicated across more than one
|
|
||||||
geographic location so as to enable resilience in the face of
|
|
||||||
catastrophic service loss.
|
|
||||||
extended_properties:
|
extended_properties:
|
||||||
Dictionary containing name/value pairs of storage account
|
Dictionary containing name/value pairs of storage account
|
||||||
properties. You can have a maximum of 50 extended property
|
properties. You can have a maximum of 50 extended property
|
||||||
@@ -195,14 +242,22 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
characters, only alphanumeric characters and underscores are valid
|
characters, only alphanumeric characters and underscores are valid
|
||||||
in the Name, and the name must start with a letter. The value has
|
in the Name, and the name must start with a letter. The value has
|
||||||
a maximum length of 255 characters.
|
a maximum length of 255 characters.
|
||||||
|
account_type:
|
||||||
|
Specifies whether the account supports locally-redundant storage,
|
||||||
|
geo-redundant storage, zone-redundant storage, or read access
|
||||||
|
geo-redundant storage.
|
||||||
|
Possible values are:
|
||||||
|
Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS
|
||||||
'''
|
'''
|
||||||
_validate_not_none('service_name', service_name)
|
_validate_not_none('service_name', service_name)
|
||||||
|
if geo_replication_enabled == False:
|
||||||
|
account_type = 'Standard_LRS'
|
||||||
return self._perform_put(
|
return self._perform_put(
|
||||||
self._get_storage_service_path(service_name),
|
self._get_storage_service_path(service_name),
|
||||||
_XmlSerializer.update_storage_service_input_to_xml(
|
_XmlSerializer.update_storage_service_input_to_xml(
|
||||||
description,
|
description,
|
||||||
label,
|
label,
|
||||||
geo_replication_enabled,
|
account_type,
|
||||||
extended_properties))
|
extended_properties))
|
||||||
|
|
||||||
def delete_storage_account(self, service_name):
|
def delete_storage_account(self, service_name):
|
||||||
@@ -697,6 +752,50 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
'',
|
'',
|
||||||
async=True)
|
async=True)
|
||||||
|
|
||||||
|
def rebuild_role_instance(self, service_name, deployment_name,
|
||||||
|
role_instance_name):
|
||||||
|
'''
|
||||||
|
Reinstalls the operating system on instances of web roles or worker
|
||||||
|
roles and initializes the storage resources that are used by them. If
|
||||||
|
you do not want to initialize storage resources, you can use
|
||||||
|
reimage_role_instance.
|
||||||
|
|
||||||
|
service_name: Name of the hosted service.
|
||||||
|
deployment_name: The name of the deployment.
|
||||||
|
role_instance_name: The name of the role instance.
|
||||||
|
'''
|
||||||
|
_validate_not_none('service_name', service_name)
|
||||||
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
|
_validate_not_none('role_instance_name', role_instance_name)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_deployment_path_using_name(
|
||||||
|
service_name, deployment_name) + \
|
||||||
|
'/roleinstances/' + _str(role_instance_name) + \
|
||||||
|
'?comp=rebuild&resources=allLocalDrives',
|
||||||
|
'',
|
||||||
|
async=True)
|
||||||
|
|
||||||
|
def delete_role_instances(self, service_name, deployment_name,
|
||||||
|
role_instance_names):
|
||||||
|
'''
|
||||||
|
Reinstalls the operating system on instances of web roles or worker
|
||||||
|
roles and initializes the storage resources that are used by them. If
|
||||||
|
you do not want to initialize storage resources, you can use
|
||||||
|
reimage_role_instance.
|
||||||
|
|
||||||
|
service_name: Name of the hosted service.
|
||||||
|
deployment_name: The name of the deployment.
|
||||||
|
role_instance_names: List of role instance names.
|
||||||
|
'''
|
||||||
|
_validate_not_none('service_name', service_name)
|
||||||
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
|
_validate_not_none('role_instance_names', role_instance_names)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_deployment_path_using_name(
|
||||||
|
service_name, deployment_name) + '/roleinstances/?comp=delete',
|
||||||
|
_XmlSerializer.role_instances_to_xml(role_instance_names),
|
||||||
|
async=True)
|
||||||
|
|
||||||
def check_hosted_service_name_availability(self, service_name):
|
def check_hosted_service_name_availability(self, service_name):
|
||||||
'''
|
'''
|
||||||
Checks to see if the specified hosted service name is available, or if
|
Checks to see if the specified hosted service name is available, or if
|
||||||
@@ -980,6 +1079,53 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
return self._perform_get('/' + self.subscription_id + '',
|
return self._perform_get('/' + self.subscription_id + '',
|
||||||
Subscription)
|
Subscription)
|
||||||
|
|
||||||
|
#--Operations for reserved ip addresses -----------------------------
|
||||||
|
def create_reserved_ip_address(self, name, label=None, location=None):
|
||||||
|
'''
|
||||||
|
Reserves an IPv4 address for the specified subscription.
|
||||||
|
|
||||||
|
name:
|
||||||
|
Required. Specifies the name for the reserved IP address.
|
||||||
|
label:
|
||||||
|
Optional. Specifies a label for the reserved IP address. The label
|
||||||
|
can be up to 100 characters long and can be used for your tracking
|
||||||
|
purposes.
|
||||||
|
location:
|
||||||
|
Required. Specifies the location of the reserved IP address. This
|
||||||
|
should be the same location that is assigned to the cloud service
|
||||||
|
containing the deployment that will use the reserved IP address.
|
||||||
|
To see the available locations, you can use list_locations.
|
||||||
|
'''
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_reserved_ip_path(),
|
||||||
|
_XmlSerializer.create_reserved_ip_to_xml(name, label, location))
|
||||||
|
|
||||||
|
def delete_reserved_ip_address(self, name):
|
||||||
|
'''
|
||||||
|
Deletes a reserved IP address from the specified subscription.
|
||||||
|
|
||||||
|
name: Required. Name of the reserved IP address.
|
||||||
|
'''
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
return self._perform_delete(self._get_reserved_ip_path(name))
|
||||||
|
|
||||||
|
def get_reserved_ip_address(self, name):
|
||||||
|
'''
|
||||||
|
Retrieves information about the specified reserved IP address.
|
||||||
|
|
||||||
|
name: Required. Name of the reserved IP address.
|
||||||
|
'''
|
||||||
|
_validate_not_none('name', name)
|
||||||
|
return self._perform_get(self._get_reserved_ip_path(name), ReservedIP)
|
||||||
|
|
||||||
|
def list_reserved_ip_addresses(self):
|
||||||
|
'''
|
||||||
|
Lists the IP addresses that have been reserved for the specified
|
||||||
|
subscription.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_reserved_ip_path(), ReservedIPs)
|
||||||
|
|
||||||
#--Operations for virtual machines -----------------------------------
|
#--Operations for virtual machines -----------------------------------
|
||||||
def get_role(self, service_name, deployment_name, role_name):
|
def get_role(self, service_name, deployment_name, role_name):
|
||||||
'''
|
'''
|
||||||
@@ -1004,7 +1150,13 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
data_virtual_hard_disks=None,
|
data_virtual_hard_disks=None,
|
||||||
role_size=None,
|
role_size=None,
|
||||||
role_type='PersistentVMRole',
|
role_type='PersistentVMRole',
|
||||||
virtual_network_name=None):
|
virtual_network_name=None,
|
||||||
|
resource_extension_references=None,
|
||||||
|
provision_guest_agent=None,
|
||||||
|
vm_image_name=None,
|
||||||
|
media_location=None,
|
||||||
|
dns_servers=None,
|
||||||
|
reserved_ip_name=None):
|
||||||
'''
|
'''
|
||||||
Provisions a virtual machine based on the supplied configuration.
|
Provisions a virtual machine based on the supplied configuration.
|
||||||
|
|
||||||
@@ -1025,7 +1177,8 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
WindowsConfigurationSet or LinuxConfigurationSet.
|
WindowsConfigurationSet or LinuxConfigurationSet.
|
||||||
os_virtual_hard_disk:
|
os_virtual_hard_disk:
|
||||||
Contains the parameters Windows Azure uses to create the operating
|
Contains the parameters Windows Azure uses to create the operating
|
||||||
system disk for the virtual machine.
|
system disk for the virtual machine. If you are creating a Virtual
|
||||||
|
Machine by using a VM Image, this parameter is not used.
|
||||||
network_config:
|
network_config:
|
||||||
Encapsulates the metadata required to create the virtual network
|
Encapsulates the metadata required to create the virtual network
|
||||||
configuration for a virtual machine. If you do not include a
|
configuration for a virtual machine. If you do not include a
|
||||||
@@ -1053,14 +1206,36 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
virtual_network_name:
|
virtual_network_name:
|
||||||
Specifies the name of an existing virtual network to which the
|
Specifies the name of an existing virtual network to which the
|
||||||
deployment will belong.
|
deployment will belong.
|
||||||
|
resource_extension_references:
|
||||||
|
Optional. Contains a collection of resource extensions that are to
|
||||||
|
be installed on the Virtual Machine. This element is used if
|
||||||
|
provision_guest_agent is set to True.
|
||||||
|
provision_guest_agent:
|
||||||
|
Optional. Indicates whether the VM Agent is installed on the
|
||||||
|
Virtual Machine. To run a resource extension in a Virtual Machine,
|
||||||
|
this service must be installed.
|
||||||
|
vm_image_name:
|
||||||
|
Optional. Specifies the name of the VM Image that is to be used to
|
||||||
|
create the Virtual Machine. If this is specified, the
|
||||||
|
system_config and network_config parameters are not used.
|
||||||
|
media_location:
|
||||||
|
Optional. Required if the Virtual Machine is being created from a
|
||||||
|
published VM Image. Specifies the location of the VHD file that is
|
||||||
|
created when VMImageName specifies a published VM Image.
|
||||||
|
dns_servers:
|
||||||
|
Optional. List of DNS servers (use DnsServer class) to associate
|
||||||
|
with the Virtual Machine.
|
||||||
|
reserved_ip_name:
|
||||||
|
Optional. Specifies the name of a reserved IP address that is to be
|
||||||
|
assigned to the deployment. You must run create_reserved_ip_address
|
||||||
|
before you can assign the address to the deployment using this
|
||||||
|
element.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('service_name', service_name)
|
_validate_not_none('service_name', service_name)
|
||||||
_validate_not_none('deployment_name', deployment_name)
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
_validate_not_none('deployment_slot', deployment_slot)
|
_validate_not_none('deployment_slot', deployment_slot)
|
||||||
_validate_not_none('label', label)
|
_validate_not_none('label', label)
|
||||||
_validate_not_none('role_name', role_name)
|
_validate_not_none('role_name', role_name)
|
||||||
_validate_not_none('system_config', system_config)
|
|
||||||
_validate_not_none('os_virtual_hard_disk', os_virtual_hard_disk)
|
|
||||||
return self._perform_post(
|
return self._perform_post(
|
||||||
self._get_deployment_path_using_name(service_name),
|
self._get_deployment_path_using_name(service_name),
|
||||||
_XmlSerializer.virtual_machine_deployment_to_xml(
|
_XmlSerializer.virtual_machine_deployment_to_xml(
|
||||||
@@ -1075,13 +1250,22 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
availability_set_name,
|
availability_set_name,
|
||||||
data_virtual_hard_disks,
|
data_virtual_hard_disks,
|
||||||
role_size,
|
role_size,
|
||||||
virtual_network_name),
|
virtual_network_name,
|
||||||
|
resource_extension_references,
|
||||||
|
provision_guest_agent,
|
||||||
|
vm_image_name,
|
||||||
|
media_location,
|
||||||
|
dns_servers,
|
||||||
|
reserved_ip_name),
|
||||||
async=True)
|
async=True)
|
||||||
|
|
||||||
def add_role(self, service_name, deployment_name, role_name, system_config,
|
def add_role(self, service_name, deployment_name, role_name, system_config,
|
||||||
os_virtual_hard_disk, network_config=None,
|
os_virtual_hard_disk, network_config=None,
|
||||||
availability_set_name=None, data_virtual_hard_disks=None,
|
availability_set_name=None, data_virtual_hard_disks=None,
|
||||||
role_size=None, role_type='PersistentVMRole'):
|
role_size=None, role_type='PersistentVMRole',
|
||||||
|
resource_extension_references=None,
|
||||||
|
provision_guest_agent=None, vm_image_name=None,
|
||||||
|
media_location=None):
|
||||||
'''
|
'''
|
||||||
Adds a virtual machine to an existing deployment.
|
Adds a virtual machine to an existing deployment.
|
||||||
|
|
||||||
@@ -1094,7 +1278,8 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
WindowsConfigurationSet or LinuxConfigurationSet.
|
WindowsConfigurationSet or LinuxConfigurationSet.
|
||||||
os_virtual_hard_disk:
|
os_virtual_hard_disk:
|
||||||
Contains the parameters Windows Azure uses to create the operating
|
Contains the parameters Windows Azure uses to create the operating
|
||||||
system disk for the virtual machine.
|
system disk for the virtual machine. If you are creating a Virtual
|
||||||
|
Machine by using a VM Image, this parameter is not used.
|
||||||
network_config:
|
network_config:
|
||||||
Encapsulates the metadata required to create the virtual network
|
Encapsulates the metadata required to create the virtual network
|
||||||
configuration for a virtual machine. If you do not include a
|
configuration for a virtual machine. If you do not include a
|
||||||
@@ -1119,12 +1304,26 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
role_type:
|
role_type:
|
||||||
The type of the role for the virtual machine. The only supported
|
The type of the role for the virtual machine. The only supported
|
||||||
value is PersistentVMRole.
|
value is PersistentVMRole.
|
||||||
|
resource_extension_references:
|
||||||
|
Optional. Contains a collection of resource extensions that are to
|
||||||
|
be installed on the Virtual Machine. This element is used if
|
||||||
|
provision_guest_agent is set to True.
|
||||||
|
provision_guest_agent:
|
||||||
|
Optional. Indicates whether the VM Agent is installed on the
|
||||||
|
Virtual Machine. To run a resource extension in a Virtual Machine,
|
||||||
|
this service must be installed.
|
||||||
|
vm_image_name:
|
||||||
|
Optional. Specifies the name of the VM Image that is to be used to
|
||||||
|
create the Virtual Machine. If this is specified, the
|
||||||
|
system_config and network_config parameters are not used.
|
||||||
|
media_location:
|
||||||
|
Optional. Required if the Virtual Machine is being created from a
|
||||||
|
published VM Image. Specifies the location of the VHD file that is
|
||||||
|
created when VMImageName specifies a published VM Image.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('service_name', service_name)
|
_validate_not_none('service_name', service_name)
|
||||||
_validate_not_none('deployment_name', deployment_name)
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
_validate_not_none('role_name', role_name)
|
_validate_not_none('role_name', role_name)
|
||||||
_validate_not_none('system_config', system_config)
|
|
||||||
_validate_not_none('os_virtual_hard_disk', os_virtual_hard_disk)
|
|
||||||
return self._perform_post(
|
return self._perform_post(
|
||||||
self._get_role_path(service_name, deployment_name),
|
self._get_role_path(service_name, deployment_name),
|
||||||
_XmlSerializer.add_role_to_xml(
|
_XmlSerializer.add_role_to_xml(
|
||||||
@@ -1135,13 +1334,19 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
network_config,
|
network_config,
|
||||||
availability_set_name,
|
availability_set_name,
|
||||||
data_virtual_hard_disks,
|
data_virtual_hard_disks,
|
||||||
role_size),
|
role_size,
|
||||||
|
resource_extension_references,
|
||||||
|
provision_guest_agent,
|
||||||
|
vm_image_name,
|
||||||
|
media_location),
|
||||||
async=True)
|
async=True)
|
||||||
|
|
||||||
def update_role(self, service_name, deployment_name, role_name,
|
def update_role(self, service_name, deployment_name, role_name,
|
||||||
os_virtual_hard_disk=None, network_config=None,
|
os_virtual_hard_disk=None, network_config=None,
|
||||||
availability_set_name=None, data_virtual_hard_disks=None,
|
availability_set_name=None, data_virtual_hard_disks=None,
|
||||||
role_size=None, role_type='PersistentVMRole'):
|
role_size=None, role_type='PersistentVMRole',
|
||||||
|
resource_extension_references=None,
|
||||||
|
provision_guest_agent=None):
|
||||||
'''
|
'''
|
||||||
Updates the specified virtual machine.
|
Updates the specified virtual machine.
|
||||||
|
|
||||||
@@ -1175,6 +1380,14 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
role_type:
|
role_type:
|
||||||
The type of the role for the virtual machine. The only supported
|
The type of the role for the virtual machine. The only supported
|
||||||
value is PersistentVMRole.
|
value is PersistentVMRole.
|
||||||
|
resource_extension_references:
|
||||||
|
Optional. Contains a collection of resource extensions that are to
|
||||||
|
be installed on the Virtual Machine. This element is used if
|
||||||
|
provision_guest_agent is set to True.
|
||||||
|
provision_guest_agent:
|
||||||
|
Optional. Indicates whether the VM Agent is installed on the
|
||||||
|
Virtual Machine. To run a resource extension in a Virtual Machine,
|
||||||
|
this service must be installed.
|
||||||
'''
|
'''
|
||||||
_validate_not_none('service_name', service_name)
|
_validate_not_none('service_name', service_name)
|
||||||
_validate_not_none('deployment_name', deployment_name)
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
@@ -1188,7 +1401,9 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
network_config,
|
network_config,
|
||||||
availability_set_name,
|
availability_set_name,
|
||||||
data_virtual_hard_disks,
|
data_virtual_hard_disks,
|
||||||
role_size),
|
role_size,
|
||||||
|
resource_extension_references,
|
||||||
|
provision_guest_agent),
|
||||||
async=True)
|
async=True)
|
||||||
|
|
||||||
def delete_role(self, service_name, deployment_name, role_name):
|
def delete_role(self, service_name, deployment_name, role_name):
|
||||||
@@ -1354,7 +1569,307 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
role_names, post_shutdown_action),
|
role_names, post_shutdown_action),
|
||||||
async=True)
|
async=True)
|
||||||
|
|
||||||
|
def add_dns_server(self, service_name, deployment_name, dns_server_name, address):
|
||||||
|
'''
|
||||||
|
Adds a DNS server definition to an existing deployment.
|
||||||
|
|
||||||
|
service_name: The name of the service.
|
||||||
|
deployment_name: The name of the deployment.
|
||||||
|
dns_server_name: Specifies the name of the DNS server.
|
||||||
|
address: Specifies the IP address of the DNS server.
|
||||||
|
'''
|
||||||
|
_validate_not_none('service_name', service_name)
|
||||||
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
|
_validate_not_none('dns_server_name', dns_server_name)
|
||||||
|
_validate_not_none('address', address)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_dns_server_path(service_name, deployment_name),
|
||||||
|
_XmlSerializer.dns_server_to_xml(dns_server_name, address),
|
||||||
|
async=True)
|
||||||
|
|
||||||
|
def update_dns_server(self, service_name, deployment_name, dns_server_name, address):
|
||||||
|
'''
|
||||||
|
Updates the ip address of a DNS server.
|
||||||
|
|
||||||
|
service_name: The name of the service.
|
||||||
|
deployment_name: The name of the deployment.
|
||||||
|
dns_server_name: Specifies the name of the DNS server.
|
||||||
|
address: Specifies the IP address of the DNS server.
|
||||||
|
'''
|
||||||
|
_validate_not_none('service_name', service_name)
|
||||||
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
|
_validate_not_none('dns_server_name', dns_server_name)
|
||||||
|
_validate_not_none('address', address)
|
||||||
|
return self._perform_put(
|
||||||
|
self._get_dns_server_path(service_name,
|
||||||
|
deployment_name,
|
||||||
|
dns_server_name),
|
||||||
|
_XmlSerializer.dns_server_to_xml(dns_server_name, address),
|
||||||
|
async=True)
|
||||||
|
|
||||||
|
def delete_dns_server(self, service_name, deployment_name, dns_server_name):
|
||||||
|
'''
|
||||||
|
Deletes a DNS server from a deployment.
|
||||||
|
|
||||||
|
service_name: The name of the service.
|
||||||
|
deployment_name: The name of the deployment.
|
||||||
|
dns_server_name: Name of the DNS server that you want to delete.
|
||||||
|
'''
|
||||||
|
_validate_not_none('service_name', service_name)
|
||||||
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
|
_validate_not_none('dns_server_name', dns_server_name)
|
||||||
|
return self._perform_delete(
|
||||||
|
self._get_dns_server_path(service_name,
|
||||||
|
deployment_name,
|
||||||
|
dns_server_name),
|
||||||
|
async=True)
|
||||||
|
|
||||||
|
def list_resource_extensions(self):
|
||||||
|
'''
|
||||||
|
Lists the resource extensions that are available to add to a
|
||||||
|
Virtual Machine.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_resource_extensions_path(),
|
||||||
|
ResourceExtensions)
|
||||||
|
|
||||||
|
def list_resource_extension_versions(self, publisher_name, extension_name):
|
||||||
|
'''
|
||||||
|
Lists the versions of a resource extension that are available to add
|
||||||
|
to a Virtual Machine.
|
||||||
|
|
||||||
|
publisher_name: Name of the resource extension publisher.
|
||||||
|
extension_name: Name of the resource extension.
|
||||||
|
'''
|
||||||
|
return self._perform_get(self._get_resource_extension_versions_path(
|
||||||
|
publisher_name, extension_name),
|
||||||
|
ResourceExtensions)
|
||||||
|
|
||||||
#--Operations for virtual machine images -----------------------------
|
#--Operations for virtual machine images -----------------------------
|
||||||
|
def capture_vm_image(self, service_name, deployment_name, role_name, options):
|
||||||
|
'''
|
||||||
|
Creates a copy of the operating system virtual hard disk (VHD) and all
|
||||||
|
of the data VHDs that are associated with the Virtual Machine, saves
|
||||||
|
the VHD copies in the same storage location as the original VHDs, and
|
||||||
|
registers the copies as a VM Image in the image repository that is
|
||||||
|
associated with the specified subscription.
|
||||||
|
|
||||||
|
service_name: The name of the service.
|
||||||
|
deployment_name: The name of the deployment.
|
||||||
|
role_name: The name of the role.
|
||||||
|
options: An instance of CaptureRoleAsVMImage class.
|
||||||
|
options.os_state:
|
||||||
|
Required. Specifies the state of the operating system in the image.
|
||||||
|
Possible values are: Generalized, Specialized
|
||||||
|
A Virtual Machine that is fully configured and running contains a
|
||||||
|
Specialized operating system. A Virtual Machine on which the
|
||||||
|
Sysprep command has been run with the generalize option contains a
|
||||||
|
Generalized operating system. If you capture an image from a
|
||||||
|
generalized Virtual Machine, the machine is deleted after the image
|
||||||
|
is captured. It is recommended that all Virtual Machines are shut
|
||||||
|
down before capturing an image.
|
||||||
|
options.vm_image_name:
|
||||||
|
Required. Specifies the name of the VM Image.
|
||||||
|
options.vm_image_name:
|
||||||
|
Required. Specifies the label of the VM Image.
|
||||||
|
options.description:
|
||||||
|
Optional. Specifies the description of the VM Image.
|
||||||
|
options.language:
|
||||||
|
Optional. Specifies the language of the VM Image.
|
||||||
|
options.image_family:
|
||||||
|
Optional. Specifies a value that can be used to group VM Images.
|
||||||
|
options.recommended_vm_size:
|
||||||
|
Optional. Specifies the size to use for the Virtual Machine that
|
||||||
|
is created from the VM Image.
|
||||||
|
'''
|
||||||
|
_validate_not_none('service_name', service_name)
|
||||||
|
_validate_not_none('deployment_name', deployment_name)
|
||||||
|
_validate_not_none('role_name', role_name)
|
||||||
|
_validate_not_none('options', options)
|
||||||
|
_validate_not_none('options.os_state', options.os_state)
|
||||||
|
_validate_not_none('options.vm_image_name', options.vm_image_name)
|
||||||
|
_validate_not_none('options.vm_image_label', options.vm_image_label)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_capture_vm_image_path(service_name, deployment_name, role_name),
|
||||||
|
_XmlSerializer.capture_vm_image_to_xml(options),
|
||||||
|
async=True)
|
||||||
|
|
||||||
|
def create_vm_image(self, vm_image):
|
||||||
|
'''
|
||||||
|
Creates a VM Image in the image repository that is associated with the
|
||||||
|
specified subscription using a specified set of virtual hard disks.
|
||||||
|
|
||||||
|
vm_image: An instance of VMImage class.
|
||||||
|
vm_image.name: Required. Specifies the name of the image.
|
||||||
|
vm_image.label: Required. Specifies an identifier for the image.
|
||||||
|
vm_image.description: Optional. Specifies the description of the image.
|
||||||
|
vm_image.os_disk_configuration:
|
||||||
|
Required. Specifies configuration information for the operating
|
||||||
|
system disk that is associated with the image.
|
||||||
|
vm_image.os_disk_configuration.host_caching:
|
||||||
|
Optional. Specifies the caching behavior of the operating system disk.
|
||||||
|
Possible values are: None, ReadOnly, ReadWrite
|
||||||
|
vm_image.os_disk_configuration.os_state:
|
||||||
|
Required. Specifies the state of the operating system in the image.
|
||||||
|
Possible values are: Generalized, Specialized
|
||||||
|
A Virtual Machine that is fully configured and running contains a
|
||||||
|
Specialized operating system. A Virtual Machine on which the
|
||||||
|
Sysprep command has been run with the generalize option contains a
|
||||||
|
Generalized operating system.
|
||||||
|
vm_image.os_disk_configuration.os:
|
||||||
|
Required. Specifies the operating system type of the image.
|
||||||
|
vm_image.os_disk_configuration.media_link:
|
||||||
|
Required. Specifies the location of the blob in Windows Azure
|
||||||
|
storage. The blob location belongs to a storage account in the
|
||||||
|
subscription specified by the <subscription-id> value in the
|
||||||
|
operation call.
|
||||||
|
vm_image.data_disk_configurations:
|
||||||
|
Optional. Specifies configuration information for the data disks
|
||||||
|
that are associated with the image. A VM Image might not have data
|
||||||
|
disks associated with it.
|
||||||
|
vm_image.data_disk_configurations[].host_caching:
|
||||||
|
Optional. Specifies the caching behavior of the data disk.
|
||||||
|
Possible values are: None, ReadOnly, ReadWrite
|
||||||
|
vm_image.data_disk_configurations[].lun:
|
||||||
|
Optional if the lun for the disk is 0. Specifies the Logical Unit
|
||||||
|
Number (LUN) for the data disk.
|
||||||
|
vm_image.data_disk_configurations[].media_link:
|
||||||
|
Required. Specifies the location of the blob in Windows Azure
|
||||||
|
storage. The blob location belongs to a storage account in the
|
||||||
|
subscription specified by the <subscription-id> value in the
|
||||||
|
operation call.
|
||||||
|
vm_image.data_disk_configurations[].logical_size_in_gb:
|
||||||
|
Required. Specifies the size, in GB, of the data disk.
|
||||||
|
vm_image.language: Optional. Specifies the language of the image.
|
||||||
|
vm_image.image_family:
|
||||||
|
Optional. Specifies a value that can be used to group VM Images.
|
||||||
|
vm_image.recommended_vm_size:
|
||||||
|
Optional. Specifies the size to use for the Virtual Machine that
|
||||||
|
is created from the VM Image.
|
||||||
|
vm_image.eula:
|
||||||
|
Optional. Specifies the End User License Agreement that is
|
||||||
|
associated with the image. The value for this element is a string,
|
||||||
|
but it is recommended that the value be a URL that points to a EULA.
|
||||||
|
vm_image.icon_uri:
|
||||||
|
Optional. Specifies the URI to the icon that is displayed for the
|
||||||
|
image in the Management Portal.
|
||||||
|
vm_image.small_icon_uri:
|
||||||
|
Optional. Specifies the URI to the small icon that is displayed for
|
||||||
|
the image in the Management Portal.
|
||||||
|
vm_image.privacy_uri:
|
||||||
|
Optional. Specifies the URI that points to a document that contains
|
||||||
|
the privacy policy related to the image.
|
||||||
|
vm_image.published_date:
|
||||||
|
Optional. Specifies the date when the image was added to the image
|
||||||
|
repository.
|
||||||
|
vm_image.show_in_gui:
|
||||||
|
Optional. Indicates whether the VM Images should be listed in the
|
||||||
|
portal.
|
||||||
|
'''
|
||||||
|
_validate_not_none('vm_image', vm_image)
|
||||||
|
_validate_not_none('vm_image.name', vm_image.name)
|
||||||
|
_validate_not_none('vm_image.label', vm_image.label)
|
||||||
|
_validate_not_none('vm_image.os_disk_configuration.os_state',
|
||||||
|
vm_image.os_disk_configuration.os_state)
|
||||||
|
_validate_not_none('vm_image.os_disk_configuration.os',
|
||||||
|
vm_image.os_disk_configuration.os)
|
||||||
|
_validate_not_none('vm_image.os_disk_configuration.media_link',
|
||||||
|
vm_image.os_disk_configuration.media_link)
|
||||||
|
return self._perform_post(
|
||||||
|
self._get_vm_image_path(),
|
||||||
|
_XmlSerializer.create_vm_image_to_xml(vm_image),
|
||||||
|
async=True)
|
||||||
|
|
||||||
|
def delete_vm_image(self, vm_image_name, delete_vhd=False):
|
||||||
|
'''
|
||||||
|
Deletes the specified VM Image from the image repository that is
|
||||||
|
associated with the specified subscription.
|
||||||
|
|
||||||
|
vm_image_name: The name of the image.
|
||||||
|
delete_vhd: Deletes the underlying vhd blob in Azure storage.
|
||||||
|
'''
|
||||||
|
_validate_not_none('vm_image_name', vm_image_name)
|
||||||
|
path = self._get_vm_image_path(vm_image_name)
|
||||||
|
if delete_vhd:
|
||||||
|
path += '?comp=media'
|
||||||
|
return self._perform_delete(path, async=True)
|
||||||
|
|
||||||
|
def list_vm_images(self, location=None, publisher=None, category=None):
|
||||||
|
'''
|
||||||
|
Retrieves a list of the VM Images from the image repository that is
|
||||||
|
associated with the specified subscription.
|
||||||
|
'''
|
||||||
|
path = self._get_vm_image_path()
|
||||||
|
query = ''
|
||||||
|
if location:
|
||||||
|
query += '&location=' + location
|
||||||
|
if publisher:
|
||||||
|
query += '&publisher=' + publisher
|
||||||
|
if category:
|
||||||
|
query += '&category=' + category
|
||||||
|
if query:
|
||||||
|
path = path + '?' + query.lstrip('&')
|
||||||
|
return self._perform_get(path, VMImages)
|
||||||
|
|
||||||
|
def update_vm_image(self, vm_image_name, vm_image):
|
||||||
|
'''
|
||||||
|
Updates a VM Image in the image repository that is associated with the
|
||||||
|
specified subscription.
|
||||||
|
|
||||||
|
vm_image_name: Name of image to update.
|
||||||
|
vm_image: An instance of VMImage class.
|
||||||
|
vm_image.label: Optional. Specifies an identifier for the image.
|
||||||
|
vm_image.os_disk_configuration:
|
||||||
|
Required. Specifies configuration information for the operating
|
||||||
|
system disk that is associated with the image.
|
||||||
|
vm_image.os_disk_configuration.host_caching:
|
||||||
|
Optional. Specifies the caching behavior of the operating system disk.
|
||||||
|
Possible values are: None, ReadOnly, ReadWrite
|
||||||
|
vm_image.data_disk_configurations:
|
||||||
|
Optional. Specifies configuration information for the data disks
|
||||||
|
that are associated with the image. A VM Image might not have data
|
||||||
|
disks associated with it.
|
||||||
|
vm_image.data_disk_configurations[].name:
|
||||||
|
Required. Specifies the name of the data disk.
|
||||||
|
vm_image.data_disk_configurations[].host_caching:
|
||||||
|
Optional. Specifies the caching behavior of the data disk.
|
||||||
|
Possible values are: None, ReadOnly, ReadWrite
|
||||||
|
vm_image.data_disk_configurations[].lun:
|
||||||
|
Optional if the lun for the disk is 0. Specifies the Logical Unit
|
||||||
|
Number (LUN) for the data disk.
|
||||||
|
vm_image.description: Optional. Specifies the description of the image.
|
||||||
|
vm_image.language: Optional. Specifies the language of the image.
|
||||||
|
vm_image.image_family:
|
||||||
|
Optional. Specifies a value that can be used to group VM Images.
|
||||||
|
vm_image.recommended_vm_size:
|
||||||
|
Optional. Specifies the size to use for the Virtual Machine that
|
||||||
|
is created from the VM Image.
|
||||||
|
vm_image.eula:
|
||||||
|
Optional. Specifies the End User License Agreement that is
|
||||||
|
associated with the image. The value for this element is a string,
|
||||||
|
but it is recommended that the value be a URL that points to a EULA.
|
||||||
|
vm_image.icon_uri:
|
||||||
|
Optional. Specifies the URI to the icon that is displayed for the
|
||||||
|
image in the Management Portal.
|
||||||
|
vm_image.small_icon_uri:
|
||||||
|
Optional. Specifies the URI to the small icon that is displayed for
|
||||||
|
the image in the Management Portal.
|
||||||
|
vm_image.privacy_uri:
|
||||||
|
Optional. Specifies the URI that points to a document that contains
|
||||||
|
the privacy policy related to the image.
|
||||||
|
vm_image.published_date:
|
||||||
|
Optional. Specifies the date when the image was added to the image
|
||||||
|
repository.
|
||||||
|
vm_image.show_in_gui:
|
||||||
|
Optional. Indicates whether the VM Images should be listed in the
|
||||||
|
portal.
|
||||||
|
'''
|
||||||
|
_validate_not_none('vm_image_name', vm_image_name)
|
||||||
|
_validate_not_none('vm_image', vm_image)
|
||||||
|
return self._perform_put(self._get_vm_image_path(vm_image_name),
|
||||||
|
_XmlSerializer.update_vm_image_to_xml(vm_image),
|
||||||
|
async=True)
|
||||||
|
|
||||||
|
#--Operations for operating system images ----------------------------
|
||||||
def list_os_images(self):
|
def list_os_images(self):
|
||||||
'''
|
'''
|
||||||
Retrieves a list of the OS images from the image repository.
|
Retrieves a list of the OS images from the image repository.
|
||||||
@@ -1707,6 +2222,12 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
return self._perform_get(self._get_virtual_network_site_path(), VirtualNetworkSites)
|
return self._perform_get(self._get_virtual_network_site_path(), VirtualNetworkSites)
|
||||||
|
|
||||||
#--Helper functions --------------------------------------------------
|
#--Helper functions --------------------------------------------------
|
||||||
|
def _get_role_sizes_path(self):
|
||||||
|
return self._get_path('rolesizes', None)
|
||||||
|
|
||||||
|
def _get_subscriptions_path(self):
|
||||||
|
return '/subscriptions'
|
||||||
|
|
||||||
def _get_virtual_network_site_path(self):
|
def _get_virtual_network_site_path(self):
|
||||||
return self._get_path('services/networking/virtualnetwork', None)
|
return self._get_path('services/networking/virtualnetwork', None)
|
||||||
|
|
||||||
@@ -1741,6 +2262,31 @@ class ServiceManagementService(_ServiceManagementClient):
|
|||||||
'/deployments/' + deployment_name +
|
'/deployments/' + deployment_name +
|
||||||
'/roles/Operations', None)
|
'/roles/Operations', None)
|
||||||
|
|
||||||
|
def _get_resource_extensions_path(self):
|
||||||
|
return self._get_path('services/resourceextensions', None)
|
||||||
|
|
||||||
|
def _get_resource_extension_versions_path(self, publisher_name, extension_name):
|
||||||
|
return self._get_path('services/resourceextensions',
|
||||||
|
publisher_name + '/' + extension_name)
|
||||||
|
|
||||||
|
def _get_dns_server_path(self, service_name, deployment_name,
|
||||||
|
dns_server_name=None):
|
||||||
|
return self._get_path('services/hostedservices/' + _str(service_name) +
|
||||||
|
'/deployments/' + deployment_name +
|
||||||
|
'/dnsservers', dns_server_name)
|
||||||
|
|
||||||
|
def _get_capture_vm_image_path(self, service_name, deployment_name, role_name):
|
||||||
|
return self._get_path('services/hostedservices/' + _str(service_name) +
|
||||||
|
'/deployments/' + _str(deployment_name) +
|
||||||
|
'/roleinstances/' + _str(role_name) + '/Operations',
|
||||||
|
None)
|
||||||
|
|
||||||
|
def _get_vm_image_path(self, image_name=None):
|
||||||
|
return self._get_path('services/vmimages', image_name)
|
||||||
|
|
||||||
|
def _get_reserved_ip_path(self, name=None):
|
||||||
|
return self._get_path('services/networking/reservedips', name)
|
||||||
|
|
||||||
def _get_data_disk_path(self, service_name, deployment_name, role_name,
|
def _get_data_disk_path(self, service_name, deployment_name, role_name,
|
||||||
lun=None):
|
lun=None):
|
||||||
return self._get_path('services/hostedservices/' + _str(service_name) +
|
return self._get_path('services/hostedservices/' + _str(service_name) +
|
||||||
|
|||||||
@@ -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/'
|
||||||
@@ -12,12 +12,12 @@
|
|||||||
# 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 hashlib
|
|
||||||
import hmac
|
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from dateutil import parser
|
||||||
|
from dateutil.tz import tzutc
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
from azure import (WindowsAzureData,
|
from azure import (WindowsAzureData,
|
||||||
WindowsAzureError,
|
WindowsAzureError,
|
||||||
@@ -36,6 +36,7 @@ from azure import (WindowsAzureData,
|
|||||||
_general_error_handler,
|
_general_error_handler,
|
||||||
_list_of,
|
_list_of,
|
||||||
_parse_response_for_dict,
|
_parse_response_for_dict,
|
||||||
|
_sign_string,
|
||||||
_unicode_type,
|
_unicode_type,
|
||||||
_ERROR_CANNOT_SERIALIZE_VALUE_TO_ENTITY,
|
_ERROR_CANNOT_SERIALIZE_VALUE_TO_ENTITY,
|
||||||
)
|
)
|
||||||
@@ -408,7 +409,7 @@ def _update_storage_header(request):
|
|||||||
if request.body:
|
if request.body:
|
||||||
assert isinstance(request.body, bytes)
|
assert isinstance(request.body, bytes)
|
||||||
|
|
||||||
# if it is PUT, POST, MERGE, DELETE, need to add content-lengt to header.
|
# if it is PUT, POST, MERGE, DELETE, need to add content-length to header.
|
||||||
if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']:
|
if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']:
|
||||||
request.headers.append(('Content-Length', str(len(request.body))))
|
request.headers.append(('Content-Length', str(len(request.body))))
|
||||||
|
|
||||||
@@ -540,17 +541,6 @@ def _sign_storage_table_request(request, account_name, account_key):
|
|||||||
return auth_string
|
return auth_string
|
||||||
|
|
||||||
|
|
||||||
def _sign_string(account_key, string_to_sign):
|
|
||||||
decoded_account_key = _decode_base64_to_bytes(account_key)
|
|
||||||
if isinstance(string_to_sign, _unicode_type):
|
|
||||||
string_to_sign = string_to_sign.encode('utf-8')
|
|
||||||
signed_hmac_sha256 = hmac.HMAC(
|
|
||||||
decoded_account_key, string_to_sign, hashlib.sha256)
|
|
||||||
digest = signed_hmac_sha256.digest()
|
|
||||||
encoded_digest = _encode_base64(digest)
|
|
||||||
return encoded_digest
|
|
||||||
|
|
||||||
|
|
||||||
def _to_python_bool(value):
|
def _to_python_bool(value):
|
||||||
if value.lower() == 'true':
|
if value.lower() == 'true':
|
||||||
return True
|
return True
|
||||||
@@ -572,7 +562,12 @@ def _to_entity_bool(value):
|
|||||||
|
|
||||||
|
|
||||||
def _to_entity_datetime(value):
|
def _to_entity_datetime(value):
|
||||||
return 'Edm.DateTime', value.strftime('%Y-%m-%dT%H:%M:%S')
|
# Azure expects the date value passed in to be UTC.
|
||||||
|
# Azure will always return values as UTC.
|
||||||
|
# If a date is passed in without timezone info, it is assumed to be UTC.
|
||||||
|
if value.tzinfo:
|
||||||
|
value = value.astimezone(tzutc())
|
||||||
|
return 'Edm.DateTime', value.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
|
||||||
|
|
||||||
def _to_entity_float(value):
|
def _to_entity_float(value):
|
||||||
@@ -607,12 +602,9 @@ def _from_entity_int(value):
|
|||||||
|
|
||||||
|
|
||||||
def _from_entity_datetime(value):
|
def _from_entity_datetime(value):
|
||||||
format = '%Y-%m-%dT%H:%M:%S'
|
# Note that Azure always returns UTC datetime, and dateutil parser
|
||||||
if '.' in value:
|
# will set the tzinfo on the date it returns
|
||||||
format = format + '.%f'
|
return parser.parse(value)
|
||||||
if value.endswith('Z'):
|
|
||||||
format = format + 'Z'
|
|
||||||
return datetime.strptime(value, format)
|
|
||||||
|
|
||||||
_ENTITY_TO_PYTHON_CONVERSIONS = {
|
_ENTITY_TO_PYTHON_CONVERSIONS = {
|
||||||
'Edm.Binary': _from_entity_binary,
|
'Edm.Binary': _from_entity_binary,
|
||||||
@@ -705,7 +697,7 @@ def _convert_entity_to_xml(source):
|
|||||||
|
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
if isinstance(properties_str, unicode):
|
if isinstance(properties_str, unicode):
|
||||||
properties_str = properties_str.encode(encoding='utf-8')
|
properties_str = properties_str.encode('utf-8')
|
||||||
|
|
||||||
# generate the entity_body
|
# generate the entity_body
|
||||||
entity_body = entity_body.format(properties=properties_str)
|
entity_body = entity_body.format(properties=properties_str)
|
||||||
@@ -835,10 +827,6 @@ def _convert_xml_to_entity(xmlstr):
|
|||||||
# extract each property node and get the type from attribute and node value
|
# extract each property node and get the type from attribute and node value
|
||||||
for xml_property in xml_properties[0].childNodes:
|
for xml_property in xml_properties[0].childNodes:
|
||||||
name = _remove_prefix(xml_property.nodeName)
|
name = _remove_prefix(xml_property.nodeName)
|
||||||
# exclude the Timestamp since it is auto added by azure when
|
|
||||||
# inserting entity. We don't want this to mix with real properties
|
|
||||||
if name in ['Timestamp']:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if xml_property.firstChild:
|
if xml_property.firstChild:
|
||||||
value = xml_property.firstChild.nodeValue
|
value = xml_property.firstChild.nodeValue
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ else:
|
|||||||
# Keep this value sync with _ERROR_PAGE_BLOB_SIZE_ALIGNMENT
|
# Keep this value sync with _ERROR_PAGE_BLOB_SIZE_ALIGNMENT
|
||||||
_PAGE_SIZE = 512
|
_PAGE_SIZE = 512
|
||||||
|
|
||||||
|
|
||||||
class BlobService(_StorageClient):
|
class BlobService(_StorageClient):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@@ -101,6 +102,7 @@ class BlobService(_StorageClient):
|
|||||||
Live host base url. If not specified, uses the host base specified
|
Live host base url. If not specified, uses the host base specified
|
||||||
when BlobService was initialized.
|
when BlobService was initialized.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if not account_name:
|
if not account_name:
|
||||||
account_name = self.account_name
|
account_name = self.account_name
|
||||||
if not protocol:
|
if not protocol:
|
||||||
@@ -553,6 +555,7 @@ class BlobService(_StorageClient):
|
|||||||
request, self.use_local_storage)
|
request, self.use_local_storage)
|
||||||
request.headers = _update_storage_blob_header(
|
request.headers = _update_storage_blob_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(response)
|
return _parse_response_for_dict(response)
|
||||||
@@ -740,26 +743,6 @@ class BlobService(_StorageClient):
|
|||||||
_validate_not_none('container_name', container_name)
|
_validate_not_none('container_name', container_name)
|
||||||
_validate_not_none('blob_name', blob_name)
|
_validate_not_none('blob_name', blob_name)
|
||||||
_validate_not_none('file_path', file_path)
|
_validate_not_none('file_path', file_path)
|
||||||
request = HTTPRequest()
|
|
||||||
request.method = 'PUT'
|
|
||||||
request.host = self._get_host()
|
|
||||||
request.path = '/' + _str(container_name) + '/' + _str(blob_name) + ''
|
|
||||||
request.headers = [
|
|
||||||
('x-ms-blob-type', 'BlockBlob'),
|
|
||||||
('Content-Encoding', _str_or_none(content_encoding)),
|
|
||||||
('Content-Language', _str_or_none(content_language)),
|
|
||||||
('Content-MD5', _str_or_none(content_md5)),
|
|
||||||
('Cache-Control', _str_or_none(cache_control)),
|
|
||||||
('x-ms-blob-content-type', _str_or_none(x_ms_blob_content_type)),
|
|
||||||
('x-ms-blob-content-encoding',
|
|
||||||
_str_or_none(x_ms_blob_content_encoding)),
|
|
||||||
('x-ms-blob-content-language',
|
|
||||||
_str_or_none(x_ms_blob_content_language)),
|
|
||||||
('x-ms-blob-content-md5', _str_or_none(x_ms_blob_content_md5)),
|
|
||||||
('x-ms-blob-cache-control', _str_or_none(x_ms_blob_cache_control)),
|
|
||||||
('x-ms-meta-name-values', x_ms_meta_name_values),
|
|
||||||
('x-ms-lease-id', _str_or_none(x_ms_lease_id)),
|
|
||||||
]
|
|
||||||
|
|
||||||
count = path.getsize(file_path)
|
count = path.getsize(file_path)
|
||||||
with open(file_path, 'rb') as stream:
|
with open(file_path, 'rb') as stream:
|
||||||
@@ -833,26 +816,6 @@ class BlobService(_StorageClient):
|
|||||||
_validate_not_none('container_name', container_name)
|
_validate_not_none('container_name', container_name)
|
||||||
_validate_not_none('blob_name', blob_name)
|
_validate_not_none('blob_name', blob_name)
|
||||||
_validate_not_none('stream', stream)
|
_validate_not_none('stream', stream)
|
||||||
request = HTTPRequest()
|
|
||||||
request.method = 'PUT'
|
|
||||||
request.host = self._get_host()
|
|
||||||
request.path = '/' + _str(container_name) + '/' + _str(blob_name) + ''
|
|
||||||
request.headers = [
|
|
||||||
('x-ms-blob-type', 'BlockBlob'),
|
|
||||||
('Content-Encoding', _str_or_none(content_encoding)),
|
|
||||||
('Content-Language', _str_or_none(content_language)),
|
|
||||||
('Content-MD5', _str_or_none(content_md5)),
|
|
||||||
('Cache-Control', _str_or_none(cache_control)),
|
|
||||||
('x-ms-blob-content-type', _str_or_none(x_ms_blob_content_type)),
|
|
||||||
('x-ms-blob-content-encoding',
|
|
||||||
_str_or_none(x_ms_blob_content_encoding)),
|
|
||||||
('x-ms-blob-content-language',
|
|
||||||
_str_or_none(x_ms_blob_content_language)),
|
|
||||||
('x-ms-blob-content-md5', _str_or_none(x_ms_blob_content_md5)),
|
|
||||||
('x-ms-blob-cache-control', _str_or_none(x_ms_blob_cache_control)),
|
|
||||||
('x-ms-meta-name-values', x_ms_meta_name_values),
|
|
||||||
('x-ms-lease-id', _str_or_none(x_ms_lease_id)),
|
|
||||||
]
|
|
||||||
|
|
||||||
if count and count < self._BLOB_MAX_DATA_SIZE:
|
if count and count < self._BLOB_MAX_DATA_SIZE:
|
||||||
if progress_callback:
|
if progress_callback:
|
||||||
@@ -922,7 +885,14 @@ class BlobService(_StorageClient):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
self.put_block_list(container_name, blob_name, block_ids)
|
self.put_block_list(container_name, blob_name, block_ids,
|
||||||
|
content_md5, x_ms_blob_cache_control,
|
||||||
|
x_ms_blob_content_type,
|
||||||
|
x_ms_blob_content_encoding,
|
||||||
|
x_ms_blob_content_language,
|
||||||
|
x_ms_blob_content_md5,
|
||||||
|
x_ms_meta_name_values,
|
||||||
|
x_ms_lease_id)
|
||||||
|
|
||||||
def put_block_blob_from_bytes(self, container_name, blob_name, blob,
|
def put_block_blob_from_bytes(self, container_name, blob_name, blob,
|
||||||
index=0, count=None, content_encoding=None,
|
index=0, count=None, content_encoding=None,
|
||||||
@@ -980,26 +950,6 @@ class BlobService(_StorageClient):
|
|||||||
_validate_not_none('blob', blob)
|
_validate_not_none('blob', blob)
|
||||||
_validate_not_none('index', index)
|
_validate_not_none('index', index)
|
||||||
_validate_type_bytes('blob', blob)
|
_validate_type_bytes('blob', blob)
|
||||||
request = HTTPRequest()
|
|
||||||
request.method = 'PUT'
|
|
||||||
request.host = self._get_host()
|
|
||||||
request.path = '/' + _str(container_name) + '/' + _str(blob_name) + ''
|
|
||||||
request.headers = [
|
|
||||||
('x-ms-blob-type', 'BlockBlob'),
|
|
||||||
('Content-Encoding', _str_or_none(content_encoding)),
|
|
||||||
('Content-Language', _str_or_none(content_language)),
|
|
||||||
('Content-MD5', _str_or_none(content_md5)),
|
|
||||||
('Cache-Control', _str_or_none(cache_control)),
|
|
||||||
('x-ms-blob-content-type', _str_or_none(x_ms_blob_content_type)),
|
|
||||||
('x-ms-blob-content-encoding',
|
|
||||||
_str_or_none(x_ms_blob_content_encoding)),
|
|
||||||
('x-ms-blob-content-language',
|
|
||||||
_str_or_none(x_ms_blob_content_language)),
|
|
||||||
('x-ms-blob-content-md5', _str_or_none(x_ms_blob_content_md5)),
|
|
||||||
('x-ms-blob-cache-control', _str_or_none(x_ms_blob_cache_control)),
|
|
||||||
('x-ms-meta-name-values', x_ms_meta_name_values),
|
|
||||||
('x-ms-lease-id', _str_or_none(x_ms_lease_id)),
|
|
||||||
]
|
|
||||||
|
|
||||||
if index < 0:
|
if index < 0:
|
||||||
raise TypeError(_ERROR_VALUE_NEGATIVE.format('index'))
|
raise TypeError(_ERROR_VALUE_NEGATIVE.format('index'))
|
||||||
@@ -1101,26 +1051,6 @@ class BlobService(_StorageClient):
|
|||||||
_validate_not_none('container_name', container_name)
|
_validate_not_none('container_name', container_name)
|
||||||
_validate_not_none('blob_name', blob_name)
|
_validate_not_none('blob_name', blob_name)
|
||||||
_validate_not_none('text', text)
|
_validate_not_none('text', text)
|
||||||
request = HTTPRequest()
|
|
||||||
request.method = 'PUT'
|
|
||||||
request.host = self._get_host()
|
|
||||||
request.path = '/' + _str(container_name) + '/' + _str(blob_name) + ''
|
|
||||||
request.headers = [
|
|
||||||
('x-ms-blob-type', 'BlockBlob'),
|
|
||||||
('Content-Encoding', _str_or_none(content_encoding)),
|
|
||||||
('Content-Language', _str_or_none(content_language)),
|
|
||||||
('Content-MD5', _str_or_none(content_md5)),
|
|
||||||
('Cache-Control', _str_or_none(cache_control)),
|
|
||||||
('x-ms-blob-content-type', _str_or_none(x_ms_blob_content_type)),
|
|
||||||
('x-ms-blob-content-encoding',
|
|
||||||
_str_or_none(x_ms_blob_content_encoding)),
|
|
||||||
('x-ms-blob-content-language',
|
|
||||||
_str_or_none(x_ms_blob_content_language)),
|
|
||||||
('x-ms-blob-content-md5', _str_or_none(x_ms_blob_content_md5)),
|
|
||||||
('x-ms-blob-cache-control', _str_or_none(x_ms_blob_cache_control)),
|
|
||||||
('x-ms-meta-name-values', x_ms_meta_name_values),
|
|
||||||
('x-ms-lease-id', _str_or_none(x_ms_lease_id)),
|
|
||||||
]
|
|
||||||
|
|
||||||
if not isinstance(text, bytes):
|
if not isinstance(text, bytes):
|
||||||
_validate_not_none('text_encoding', text_encoding)
|
_validate_not_none('text_encoding', text_encoding)
|
||||||
@@ -1541,7 +1471,7 @@ class BlobService(_StorageClient):
|
|||||||
|
|
||||||
index = 0
|
index = 0
|
||||||
while index < blob_size:
|
while index < blob_size:
|
||||||
chunk_range = 'bytes={}-{}'.format(
|
chunk_range = 'bytes={0}-{1}'.format(
|
||||||
index,
|
index,
|
||||||
index + self._BLOB_MAX_CHUNK_DATA_SIZE - 1)
|
index + self._BLOB_MAX_CHUNK_DATA_SIZE - 1)
|
||||||
data = self.get_blob(
|
data = self.get_blob(
|
||||||
@@ -1862,6 +1792,7 @@ class BlobService(_StorageClient):
|
|||||||
('x-ms-lease-id', _str_or_none(x_ms_lease_id)),
|
('x-ms-lease-id', _str_or_none(x_ms_lease_id)),
|
||||||
('x-ms-source-lease-id', _str_or_none(x_ms_source_lease_id))
|
('x-ms-source-lease-id', _str_or_none(x_ms_source_lease_id))
|
||||||
]
|
]
|
||||||
|
|
||||||
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_blob_header(
|
request.headers = _update_storage_blob_header(
|
||||||
@@ -1904,7 +1835,8 @@ class BlobService(_StorageClient):
|
|||||||
self._perform_request(request)
|
self._perform_request(request)
|
||||||
|
|
||||||
def delete_blob(self, container_name, blob_name, snapshot=None,
|
def delete_blob(self, container_name, blob_name, snapshot=None,
|
||||||
x_ms_lease_id=None):
|
timeout=None, x_ms_lease_id=None,
|
||||||
|
x_ms_delete_snapshots=None):
|
||||||
'''
|
'''
|
||||||
Marks the specified blob or snapshot for deletion. The blob is later
|
Marks the specified blob or snapshot for deletion. The blob is later
|
||||||
deleted during garbage collection.
|
deleted during garbage collection.
|
||||||
@@ -1917,7 +1849,22 @@ class BlobService(_StorageClient):
|
|||||||
snapshot:
|
snapshot:
|
||||||
Optional. The snapshot parameter is an opaque DateTime value that,
|
Optional. The snapshot parameter is an opaque DateTime value that,
|
||||||
when present, specifies the blob snapshot to delete.
|
when present, specifies the blob snapshot to delete.
|
||||||
|
timeout:
|
||||||
|
Optional. The timeout parameter is expressed in seconds.
|
||||||
|
The Blob service returns an error when the timeout interval elapses
|
||||||
|
while processing the request.
|
||||||
x_ms_lease_id: Required if the blob has an active lease.
|
x_ms_lease_id: Required if the blob has an active lease.
|
||||||
|
x_ms_delete_snapshots:
|
||||||
|
Required if the blob has associated snapshots. Specify one of the
|
||||||
|
following two options:
|
||||||
|
include: Delete the base blob and all of its snapshots.
|
||||||
|
only: Delete only the blob's snapshots and not the blob itself.
|
||||||
|
This header should be specified only for a request against the base
|
||||||
|
blob resource. If this header is specified on a request to delete
|
||||||
|
an individual snapshot, the Blob service returns status code 400
|
||||||
|
(Bad Request). If this header is not specified on the request and
|
||||||
|
the blob has associated snapshots, the Blob service returns status
|
||||||
|
code 409 (Conflict).
|
||||||
'''
|
'''
|
||||||
_validate_not_none('container_name', container_name)
|
_validate_not_none('container_name', container_name)
|
||||||
_validate_not_none('blob_name', blob_name)
|
_validate_not_none('blob_name', blob_name)
|
||||||
@@ -1925,8 +1872,14 @@ class BlobService(_StorageClient):
|
|||||||
request.method = 'DELETE'
|
request.method = 'DELETE'
|
||||||
request.host = self._get_host()
|
request.host = self._get_host()
|
||||||
request.path = '/' + _str(container_name) + '/' + _str(blob_name) + ''
|
request.path = '/' + _str(container_name) + '/' + _str(blob_name) + ''
|
||||||
request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))]
|
request.headers = [
|
||||||
request.query = [('snapshot', _str_or_none(snapshot))]
|
('x-ms-lease-id', _str_or_none(x_ms_lease_id)),
|
||||||
|
('x-ms-delete-snapshots', _str_or_none(x_ms_delete_snapshots))
|
||||||
|
]
|
||||||
|
request.query = [
|
||||||
|
('snapshot', _str_or_none(snapshot)),
|
||||||
|
('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_blob_header(
|
request.headers = _update_storage_blob_header(
|
||||||
|
|||||||
@@ -12,11 +12,12 @@
|
|||||||
# 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_VERSION = 'sv'
|
||||||
SIGNED_START = 'st'
|
SIGNED_START = 'st'
|
||||||
SIGNED_EXPIRY = 'se'
|
SIGNED_EXPIRY = 'se'
|
||||||
SIGNED_RESOURCE = 'sr'
|
SIGNED_RESOURCE = 'sr'
|
||||||
|
|||||||
Reference in New Issue
Block a user