mirror of
https://github.com/ansible/awx.git
synced 2026-05-23 08:37:48 -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/*)
|
||||
anyjson==0.3.3 (anyjson/*)
|
||||
argparse==1.2.1 (argparse.py, needed for Python 2.6 support)
|
||||
azure==0.9.0 (azure/*)
|
||||
Babel==1.3 (babel/*, excluded bin/pybabel)
|
||||
billiard==3.3.0.16 (billiard/*, funtests/*, excluded _billiard.so)
|
||||
boto==2.34.0 (boto/*, excluded bin/asadmin, bin/bundle_image, bin/cfadmin,
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#--------------------------------------------------------------------------
|
||||
import ast
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import sys
|
||||
import types
|
||||
import warnings
|
||||
@@ -34,7 +36,7 @@ from xml.sax.saxutils import escape as xml_escape
|
||||
# constants
|
||||
|
||||
__author__ = 'Microsoft Corp. <ptvshelp@microsoft.com>'
|
||||
__version__ = '0.8.1'
|
||||
__version__ = '0.9.0'
|
||||
|
||||
# Live ServiceClient URLs
|
||||
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. '''
|
||||
pass
|
||||
|
||||
|
||||
class WindowsAzureError(Exception):
|
||||
|
||||
''' WindowsAzure Excpetion base class. '''
|
||||
''' WindowsAzure Exception base class. '''
|
||||
|
||||
def __init__(self, message):
|
||||
super(WindowsAzureError, self).__init__(message)
|
||||
@@ -188,25 +189,38 @@ def _get_readable_id(id_name, id_prefix_to_skip):
|
||||
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):
|
||||
''' get properties from entry xml '''
|
||||
xmldoc = minidom.parseString(xmlstr)
|
||||
properties = {}
|
||||
|
||||
for entry in _get_child_nodes(xmldoc, 'entry'):
|
||||
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:
|
||||
for id in _get_child_nodes(entry, 'id'):
|
||||
properties['name'] = _get_readable_id(
|
||||
id.firstChild.nodeValue, id_prefix_to_skip)
|
||||
properties.update(_get_entry_properties_from_node(entry, include_id, id_prefix_to_skip))
|
||||
|
||||
return properties
|
||||
|
||||
@@ -284,6 +298,18 @@ _KNOWN_SERIALIZATION_XFORMS = {
|
||||
'os': 'OS',
|
||||
'persistent_vm_downtime_info': 'PersistentVMDowntimeInfo',
|
||||
'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
|
||||
|
||||
|
||||
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):
|
||||
if not isinstance(param, bytes):
|
||||
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)
|
||||
|
||||
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):
|
||||
members = dict(vars(return_obj))
|
||||
@@ -700,6 +752,12 @@ def _fill_data_to_return_object(node, return_obj):
|
||||
value.pair_xml_element_name,
|
||||
value.key_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):
|
||||
setattr(return_obj,
|
||||
name,
|
||||
@@ -737,11 +795,24 @@ def _parse_response_body_from_xml_text(respbody, return_type):
|
||||
'''
|
||||
doc = minidom.parseString(respbody)
|
||||
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)
|
||||
|
||||
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):
|
||||
|
||||
@@ -781,6 +852,15 @@ class _scalar_list_of(list):
|
||||
self.xml_element_name = xml_element_name
|
||||
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):
|
||||
''' create correct uri and query for the request '''
|
||||
@@ -903,3 +983,17 @@ def _parse_response_for_dict_filter(response, filter):
|
||||
return return_dict
|
||||
else:
|
||||
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 import _USER_AGENT_STRING, _update_request_uri_query
|
||||
|
||||
DEBUG_REQUESTS = False
|
||||
DEBUG_RESPONSES = False
|
||||
|
||||
class _HTTPClient(object):
|
||||
|
||||
@@ -44,8 +46,7 @@ class _HTTPClient(object):
|
||||
'''
|
||||
|
||||
def __init__(self, service_instance, cert_file=None, account_name=None,
|
||||
account_key=None, service_namespace=None, issuer=None,
|
||||
protocol='https'):
|
||||
account_key=None, protocol='https', request_session=None):
|
||||
'''
|
||||
service_instance: service client instance.
|
||||
cert_file:
|
||||
@@ -53,10 +54,9 @@ class _HTTPClient(object):
|
||||
service management.
|
||||
account_name: the storage account.
|
||||
account_key:
|
||||
the storage account access key for storage services or servicebus
|
||||
access key for service bus service.
|
||||
service_namespace: the service namespace for service bus.
|
||||
issuer: the issuer for service bus service.
|
||||
the storage account access key.
|
||||
request_session:
|
||||
session object created with requests library (or compatible).
|
||||
'''
|
||||
self.service_instance = service_instance
|
||||
self.status = None
|
||||
@@ -65,14 +65,16 @@ class _HTTPClient(object):
|
||||
self.cert_file = cert_file
|
||||
self.account_name = account_name
|
||||
self.account_key = account_key
|
||||
self.service_namespace = service_namespace
|
||||
self.issuer = issuer
|
||||
self.protocol = protocol
|
||||
self.proxy_host = None
|
||||
self.proxy_port = None
|
||||
self.proxy_user = 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):
|
||||
if sys.platform.lower().startswith('win') and self.cert_file:
|
||||
@@ -111,6 +113,13 @@ class _HTTPClient(object):
|
||||
self.proxy_user = user
|
||||
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):
|
||||
''' Create connection for the request. '''
|
||||
protocol = request.protocol_override \
|
||||
@@ -118,7 +127,12 @@ class _HTTPClient(object):
|
||||
target_host = request.host
|
||||
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
|
||||
connection = azure.http.winhttp._HTTPConnection(
|
||||
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_body(connection, request.body)
|
||||
|
||||
if DEBUG_REQUESTS and request.body:
|
||||
print('request:')
|
||||
try:
|
||||
print(request.body)
|
||||
except:
|
||||
pass
|
||||
|
||||
resp = connection.getresponse()
|
||||
self.status = int(resp.status)
|
||||
self.message = resp.reason
|
||||
@@ -206,6 +227,13 @@ class _HTTPClient(object):
|
||||
elif resp.length > 0:
|
||||
respbody = resp.read(resp.length)
|
||||
|
||||
if DEBUG_RESPONSES and respbody:
|
||||
print('response:')
|
||||
try:
|
||||
print(respbody)
|
||||
except:
|
||||
pass
|
||||
|
||||
response = HTTPResponse(
|
||||
int(resp.status), resp.reason, headers, respbody)
|
||||
if self.status == 307:
|
||||
|
||||
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.
|
||||
#--------------------------------------------------------------------------
|
||||
import ast
|
||||
import json
|
||||
import sys
|
||||
|
||||
from datetime import datetime
|
||||
@@ -167,16 +168,16 @@ class Message(WindowsAzureData):
|
||||
# extracts the topic and subscriptions name if it is topic message.
|
||||
if location:
|
||||
if '/subscriptions/' in location:
|
||||
pos = location.find('/subscriptions/')
|
||||
pos1 = location.rfind('/', 0, pos - 1)
|
||||
self._topic_name = location[pos1 + 1:pos]
|
||||
pos += len('/subscriptions/')
|
||||
pos = location.find(service_bus_service.host_base.lower())+1
|
||||
pos1 = location.find('/subscriptions/')
|
||||
self._topic_name = location[pos+len(service_bus_service.host_base):pos1]
|
||||
pos = pos1 + len('/subscriptions/')
|
||||
pos1 = location.find('/', pos)
|
||||
self._subscription_name = location[pos:pos1]
|
||||
elif '/messages/' in location:
|
||||
pos = location.find('/messages/')
|
||||
pos1 = location.rfind('/', 0, pos - 1)
|
||||
self._queue_name = location[pos1 + 1:pos]
|
||||
pos = location.find(service_bus_service.host_base.lower())+1
|
||||
pos1 = location.find('/messages/')
|
||||
self._queue_name = location[pos+len(service_bus_service.host_base):pos1]
|
||||
|
||||
def delete(self):
|
||||
''' 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.
|
||||
for name, value in response.headers:
|
||||
if name.lower() == 'brokerproperties':
|
||||
broker_properties = ast.literal_eval(value)
|
||||
broker_properties = json.loads(value)
|
||||
elif name.lower() == 'content-type':
|
||||
message_type = value
|
||||
elif name.lower() == 'location':
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
|
||||
@@ -21,10 +22,13 @@ from azure import (
|
||||
_convert_response_to_feeds,
|
||||
_dont_fail_not_exist,
|
||||
_dont_fail_on_exist,
|
||||
_encode_base64,
|
||||
_get_request_body,
|
||||
_get_request_body_bytes_only,
|
||||
_int_or_none,
|
||||
_sign_string,
|
||||
_str,
|
||||
_unicode_type,
|
||||
_update_request_uri_query,
|
||||
url_quote,
|
||||
url_unquote,
|
||||
@@ -55,44 +59,94 @@ from azure.servicebus import (
|
||||
_service_bus_error_handler,
|
||||
)
|
||||
|
||||
# Token cache for Authentication
|
||||
# Shared by the different instances of ServiceBusService
|
||||
_tokens = {}
|
||||
|
||||
|
||||
class ServiceBusService(object):
|
||||
|
||||
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 is not used, but the parameter is kept for backwards
|
||||
# compatibility
|
||||
x_ms_version='2011-06-01', host_base=SERVICE_BUS_HOST_BASE,
|
||||
shared_access_key_name=None, shared_access_key_value=None,
|
||||
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.service_namespace = service_namespace
|
||||
self.account_key = account_key
|
||||
self.issuer = issuer
|
||||
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:
|
||||
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 \
|
||||
not self.account_key or not self.issuer:
|
||||
raise WindowsAzureError(
|
||||
'You need to provide servicebus namespace, access key and Issuer')
|
||||
if not self.service_namespace:
|
||||
raise WindowsAzureError('You need to provide servicebus namespace')
|
||||
|
||||
self._httpclient = _HTTPClient(service_instance=self,
|
||||
service_namespace=self.service_namespace,
|
||||
account_key=self.account_key,
|
||||
issuer=self.issuer)
|
||||
if authentication:
|
||||
self.authentication = authentication
|
||||
else:
|
||||
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
|
||||
|
||||
# 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):
|
||||
'''
|
||||
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
|
||||
post-processing on the response.
|
||||
'''
|
||||
res = ServiceBusService(self.service_namespace, self.account_key,
|
||||
self.issuer)
|
||||
res = ServiceBusService(
|
||||
service_namespace=self.service_namespace,
|
||||
authentication=self.authentication)
|
||||
|
||||
old_filter = self._filter
|
||||
|
||||
def new_filter(request):
|
||||
@@ -855,17 +911,30 @@ class ServiceBusService(object):
|
||||
('Content-Type',
|
||||
'application/atom+xml;type=entry;charset=utf-8'))
|
||||
|
||||
# Adds authoriaztion header for authentication.
|
||||
request.headers.append(
|
||||
('Authorization', self._sign_service_bus_request(request)))
|
||||
# Adds authorization header for authentication.
|
||||
self.authentication.sign_request(request, self._httpclient)
|
||||
|
||||
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="' + \
|
||||
self._get_token(request.host, request.path) + '"'
|
||||
self._get_token(request.host, request.path, httpclient) + '"'
|
||||
|
||||
def _token_is_expired(self, token):
|
||||
''' Check if token expires or not. '''
|
||||
@@ -878,7 +947,7 @@ class ServiceBusService(object):
|
||||
# token to server.
|
||||
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.
|
||||
|
||||
@@ -905,10 +974,38 @@ class ServiceBusService(object):
|
||||
'&wrap_scope=' +
|
||||
url_quote('http://' + host + path)).encode('utf-8')
|
||||
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 = url_unquote(token[token.find('=') + 1:token.rfind('&')])
|
||||
_tokens[wrap_scope] = 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,
|
||||
_str,
|
||||
_validate_not_none,
|
||||
)
|
||||
_convert_xml_to_windows_azure_object,
|
||||
)
|
||||
from azure.servicemanagement import (
|
||||
_ServiceBusManagementXmlSerializer,
|
||||
)
|
||||
QueueDescription,
|
||||
TopicDescription,
|
||||
NotificationHubDescription,
|
||||
RelayDescription,
|
||||
MetricProperties,
|
||||
MetricValues,
|
||||
MetricRollups,
|
||||
)
|
||||
from azure.servicemanagement.servicemanagementclient import (
|
||||
_ServiceManagementClient,
|
||||
)
|
||||
)
|
||||
|
||||
from functools import partial
|
||||
|
||||
X_MS_VERSION = '2012-03-01'
|
||||
|
||||
class ServiceBusManagementService(_ServiceManagementClient):
|
||||
|
||||
def __init__(self, subscription_id=None, cert_file=None,
|
||||
host=MANAGEMENT_HOST):
|
||||
super(ServiceBusManagementService, self).__init__(
|
||||
subscription_id, cert_file, host)
|
||||
host=MANAGEMENT_HOST, request_session=None):
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Get list of available service bus regions.
|
||||
@@ -111,3 +144,391 @@ class ServiceBusManagementService(_ServiceManagementClient):
|
||||
|
||||
return _ServiceBusManagementXmlSerializer.xml_to_namespace_availability(
|
||||
response.body)
|
||||
|
||||
def list_queues(self, name):
|
||||
'''
|
||||
Enumerates the queues in the service namespace.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
'''
|
||||
_validate_not_none('name', name)
|
||||
|
||||
response = self._perform_get(
|
||||
self._get_list_queues_path(name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_convert_xml_to_windows_azure_object,
|
||||
azure_type=QueueDescription))
|
||||
|
||||
def list_topics(self, name):
|
||||
'''
|
||||
Retrieves the topics in the service namespace.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_list_topics_path(name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_convert_xml_to_windows_azure_object,
|
||||
azure_type=TopicDescription))
|
||||
|
||||
def list_notification_hubs(self, name):
|
||||
'''
|
||||
Retrieves the notification hubs in the service namespace.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_list_notification_hubs_path(name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_convert_xml_to_windows_azure_object,
|
||||
azure_type=NotificationHubDescription))
|
||||
|
||||
def list_relays(self, name):
|
||||
'''
|
||||
Retrieves the relays in the service namespace.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_list_relays_path(name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_convert_xml_to_windows_azure_object,
|
||||
azure_type=RelayDescription))
|
||||
|
||||
def get_supported_metrics_queue(self, name, queue_name):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and queue
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
queue_name: Name of the service bus queue in this namespace.
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_supported_metrics_queue_path(name, queue_name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricProperties))
|
||||
|
||||
def get_supported_metrics_topic(self, name, topic_name):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and topic
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
topic_name: Name of the service bus queue in this namespace.
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_supported_metrics_topic_path(name, topic_name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricProperties))
|
||||
|
||||
def get_supported_metrics_notification_hub(self, name, hub_name):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and topic
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
hub_name: Name of the service bus notification hub in this namespace.
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_supported_metrics_hub_path(name, hub_name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricProperties))
|
||||
|
||||
def get_supported_metrics_relay(self, name, relay_name):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and relay
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
relay_name: Name of the service bus relay in this namespace.
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_supported_metrics_relay_path(name, relay_name),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricProperties))
|
||||
|
||||
def get_metrics_data_queue(self, name, queue_name, metric, rollup, filter_expresssion):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and queue
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
queue_name: Name of the service bus queue in this namespace.
|
||||
metric: name of a supported metric
|
||||
rollup: name of a supported rollup
|
||||
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_data_queue_path(name, queue_name, metric, rollup, filter_expresssion),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricValues))
|
||||
|
||||
def get_metrics_data_topic(self, name, topic_name, metric, rollup, filter_expresssion):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and topic
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
topic_name: Name of the service bus queue in this namespace.
|
||||
metric: name of a supported metric
|
||||
rollup: name of a supported rollup
|
||||
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_data_topic_path(name, topic_name, metric, rollup, filter_expresssion),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricValues))
|
||||
|
||||
def get_metrics_data_notification_hub(self, name, hub_name, metric, rollup, filter_expresssion):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and topic
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
hub_name: Name of the service bus notification hub in this namespace.
|
||||
metric: name of a supported metric
|
||||
rollup: name of a supported rollup
|
||||
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_data_hub_path(name, hub_name, metric, rollup, filter_expresssion),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricValues))
|
||||
|
||||
def get_metrics_data_relay(self, name, relay_name, metric, rollup, filter_expresssion):
|
||||
'''
|
||||
Retrieves the list of supported metrics for this namespace and relay
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
relay_name: Name of the service bus relay in this namespace.
|
||||
metric: name of a supported metric
|
||||
rollup: name of a supported rollup
|
||||
filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'"
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_data_relay_path(name, relay_name, metric, rollup, filter_expresssion),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricValues))
|
||||
|
||||
def get_metrics_rollups_queue(self, name, queue_name, metric):
|
||||
'''
|
||||
This operation gets rollup data for Service Bus metrics queue.
|
||||
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||
the retention settings for each time granularity.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
queue_name: Name of the service bus queue in this namespace.
|
||||
metric: name of a supported metric
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_rollup_queue_path(name, queue_name, metric),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricRollups))
|
||||
|
||||
def get_metrics_rollups_topic(self, name, topic_name, metric):
|
||||
'''
|
||||
This operation gets rollup data for Service Bus metrics topic.
|
||||
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||
the retention settings for each time granularity.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
topic_name: Name of the service bus queue in this namespace.
|
||||
metric: name of a supported metric
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_rollup_topic_path(name, topic_name, metric),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricRollups))
|
||||
|
||||
def get_metrics_rollups_notification_hub(self, name, hub_name, metric):
|
||||
'''
|
||||
This operation gets rollup data for Service Bus metrics notification hub.
|
||||
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||
the retention settings for each time granularity.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
hub_name: Name of the service bus notification hub in this namespace.
|
||||
metric: name of a supported metric
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_rollup_hub_path(name, hub_name, metric),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricRollups))
|
||||
|
||||
def get_metrics_rollups_relay(self, name, relay_name, metric):
|
||||
'''
|
||||
This operation gets rollup data for Service Bus metrics relay.
|
||||
Rollup data includes the time granularity for the telemetry aggregation as well as
|
||||
the retention settings for each time granularity.
|
||||
|
||||
name: Name of the service bus namespace.
|
||||
relay_name: Name of the service bus relay in this namespace.
|
||||
metric: name of a supported metric
|
||||
'''
|
||||
response = self._perform_get(
|
||||
self._get_get_metrics_rollup_relay_path(name, relay_name, metric),
|
||||
None)
|
||||
|
||||
return _convert_response_to_feeds(response,
|
||||
partial(_ServiceBusManagementXmlSerializer.xml_to_metrics,
|
||||
object_type=MetricRollups))
|
||||
|
||||
|
||||
# Helper functions --------------------------------------------------
|
||||
def _get_list_queues_path(self, namespace_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/Queues'
|
||||
|
||||
def _get_list_topics_path(self, namespace_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/Topics'
|
||||
|
||||
def _get_list_notification_hubs_path(self, namespace_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/NotificationHubs'
|
||||
|
||||
def _get_list_relays_path(self, namespace_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/Relays'
|
||||
|
||||
def _get_get_supported_metrics_queue_path(self, namespace_name, queue_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/Queues/' + _str(queue_name) + '/Metrics'
|
||||
|
||||
def _get_get_supported_metrics_topic_path(self, namespace_name, topic_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/Topics/' + _str(topic_name) + '/Metrics'
|
||||
|
||||
def _get_get_supported_metrics_hub_path(self, namespace_name, hub_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/NotificationHubs/' + _str(hub_name) + '/Metrics'
|
||||
|
||||
def _get_get_supported_metrics_relay_path(self, namespace_name, queue_name):
|
||||
return self._get_path('services/serviceBus/Namespaces/',
|
||||
namespace_name) + '/Relays/' + _str(queue_name) + '/Metrics'
|
||||
|
||||
def _get_get_metrics_data_queue_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/Queues/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups/',
|
||||
_str(rollup),
|
||||
'/Values?',
|
||||
filter_expr
|
||||
])
|
||||
|
||||
def _get_get_metrics_data_topic_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/Topics/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups/',
|
||||
_str(rollup),
|
||||
'/Values?',
|
||||
filter_expr
|
||||
])
|
||||
|
||||
def _get_get_metrics_data_hub_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/NotificationHubs/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups/',
|
||||
_str(rollup),
|
||||
'/Values?',
|
||||
filter_expr
|
||||
])
|
||||
|
||||
def _get_get_metrics_data_relay_path(self, namespace_name, queue_name, metric, rollup, filter_expr):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/Relays/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups/',
|
||||
_str(rollup),
|
||||
'/Values?',
|
||||
filter_expr
|
||||
])
|
||||
|
||||
def _get_get_metrics_rollup_queue_path(self, namespace_name, queue_name, metric):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/Queues/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups',
|
||||
])
|
||||
|
||||
def _get_get_metrics_rollup_topic_path(self, namespace_name, queue_name, metric):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/Topics/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups',
|
||||
])
|
||||
|
||||
def _get_get_metrics_rollup_hub_path(self, namespace_name, queue_name, metric):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/NotificationHubs/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups',
|
||||
])
|
||||
|
||||
def _get_get_metrics_rollup_relay_path(self, namespace_name, queue_name, metric):
|
||||
return "".join([
|
||||
self._get_path('services/serviceBus/Namespaces/', namespace_name),
|
||||
'/Relays/',
|
||||
_str(queue_name),
|
||||
'/Metrics/',
|
||||
_str(metric),
|
||||
'/Rollups',
|
||||
])
|
||||
|
||||
@@ -31,21 +31,24 @@ from azure.servicemanagement import (
|
||||
AZURE_MANAGEMENT_CERTFILE,
|
||||
AZURE_MANAGEMENT_SUBSCRIPTIONID,
|
||||
_management_error_handler,
|
||||
_parse_response_for_async_op,
|
||||
_update_management_header,
|
||||
parse_response_for_async_op,
|
||||
X_MS_VERSION,
|
||||
)
|
||||
|
||||
|
||||
class _ServiceManagementClient(object):
|
||||
|
||||
def __init__(self, subscription_id=None, cert_file=None,
|
||||
host=MANAGEMENT_HOST):
|
||||
host=MANAGEMENT_HOST, request_session=None):
|
||||
self.requestid = None
|
||||
self.subscription_id = subscription_id
|
||||
self.cert_file = cert_file
|
||||
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:
|
||||
self.cert_file = os.environ[AZURE_MANAGEMENT_CERTFILE]
|
||||
|
||||
@@ -54,12 +57,14 @@ class _ServiceManagementClient(object):
|
||||
self.subscription_id = os.environ[
|
||||
AZURE_MANAGEMENT_SUBSCRIPTIONID]
|
||||
|
||||
if not self.cert_file or not self.subscription_id:
|
||||
raise WindowsAzureError(
|
||||
'You need to provide subscription id and certificate file')
|
||||
if not self.request_session:
|
||||
if not self.cert_file or not self.subscription_id:
|
||||
raise WindowsAzureError(
|
||||
'You need to provide subscription id and certificate file')
|
||||
|
||||
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
|
||||
|
||||
def with_filter(self, filter):
|
||||
@@ -69,7 +74,8 @@ class _ServiceManagementClient(object):
|
||||
and another lambda. The filter can perform any pre-processing on the
|
||||
request, pass it off to the next lambda, and then perform any
|
||||
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
|
||||
|
||||
def new_filter(request):
|
||||
@@ -89,6 +95,96 @@ class _ServiceManagementClient(object):
|
||||
'''
|
||||
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 --------------------------------------------------
|
||||
def _perform_request(self, request):
|
||||
try:
|
||||
@@ -98,64 +194,60 @@ class _ServiceManagementClient(object):
|
||||
|
||||
return resp
|
||||
|
||||
def _perform_get(self, path, response_type):
|
||||
request = HTTPRequest()
|
||||
request.method = 'GET'
|
||||
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)
|
||||
def _update_management_header(self, request, x_ms_version):
|
||||
''' Add additional headers for management. '''
|
||||
|
||||
if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']:
|
||||
request.headers.append(('Content-Length', str(len(request.body))))
|
||||
|
||||
# append additional headers base on the service
|
||||
request.headers.append(('x-ms-version', x_ms_version or self.x_ms_version))
|
||||
|
||||
# if it is not GET or HEAD request, must set content-type.
|
||||
if not request.method in ['GET', 'HEAD']:
|
||||
for name, _ in request.headers:
|
||||
if 'content-type' == name.lower():
|
||||
break
|
||||
else:
|
||||
request.headers.append(
|
||||
('Content-Type',
|
||||
self.content_type))
|
||||
|
||||
return request.headers
|
||||
|
||||
def _perform_get(self, path, response_type, x_ms_version=None):
|
||||
response = self.perform_get(path, x_ms_version)
|
||||
|
||||
if response_type is not None:
|
||||
return _parse_response(response, response_type)
|
||||
|
||||
return response
|
||||
|
||||
def _perform_put(self, path, body, async=False):
|
||||
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 = _update_management_header(request)
|
||||
response = self._perform_request(request)
|
||||
def _perform_put(self, path, body, async=False, x_ms_version=None):
|
||||
response = self.perform_put(path, body, x_ms_version)
|
||||
|
||||
if async:
|
||||
return _parse_response_for_async_op(response)
|
||||
return parse_response_for_async_op(response)
|
||||
|
||||
return None
|
||||
|
||||
def _perform_post(self, path, body, response_type=None, async=False):
|
||||
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 = _update_management_header(request)
|
||||
response = self._perform_request(request)
|
||||
def _perform_post(self, path, body, response_type=None, async=False,
|
||||
x_ms_version=None):
|
||||
response = self.perform_post(path, body, x_ms_version)
|
||||
|
||||
if response_type is not None:
|
||||
return _parse_response(response, response_type)
|
||||
|
||||
if async:
|
||||
return _parse_response_for_async_op(response)
|
||||
return parse_response_for_async_op(response)
|
||||
|
||||
return None
|
||||
|
||||
def _perform_delete(self, path, async=False):
|
||||
request = HTTPRequest()
|
||||
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)
|
||||
def _perform_delete(self, path, async=False, x_ms_version=None):
|
||||
response = self.perform_delete(path, x_ms_version)
|
||||
|
||||
if async:
|
||||
return _parse_response_for_async_op(response)
|
||||
return parse_response_for_async_op(response)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@@ -37,12 +37,19 @@ from azure.servicemanagement import (
|
||||
OperatingSystemFamilies,
|
||||
OSImage,
|
||||
PersistentVMRole,
|
||||
ResourceExtensions,
|
||||
ReservedIP,
|
||||
ReservedIPs,
|
||||
RoleSize,
|
||||
RoleSizes,
|
||||
StorageService,
|
||||
StorageServices,
|
||||
Subscription,
|
||||
Subscriptions,
|
||||
SubscriptionCertificate,
|
||||
SubscriptionCertificates,
|
||||
VirtualNetworkSites,
|
||||
VMImages,
|
||||
_XmlSerializer,
|
||||
)
|
||||
from azure.servicemanagement.servicemanagementclient import (
|
||||
@@ -52,9 +59,49 @@ from azure.servicemanagement.servicemanagementclient import (
|
||||
class ServiceManagementService(_ServiceManagementClient):
|
||||
|
||||
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__(
|
||||
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 -----------------------------------
|
||||
def list_storage_accounts(self):
|
||||
@@ -107,8 +154,9 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
|
||||
def create_storage_account(self, service_name, description, label,
|
||||
affinity_group=None, location=None,
|
||||
geo_replication_enabled=True,
|
||||
extended_properties=None):
|
||||
geo_replication_enabled=None,
|
||||
extended_properties=None,
|
||||
account_type='Standard_GRS'):
|
||||
'''
|
||||
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
|
||||
either a location or affinity_group, but not both.
|
||||
geo_replication_enabled:
|
||||
Specifies whether the storage account is created with the
|
||||
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.
|
||||
Deprecated. Replaced by the account_type parameter.
|
||||
extended_properties:
|
||||
Dictionary containing name/value pairs of storage account
|
||||
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
|
||||
in the Name, and the name must start with a letter. The value has
|
||||
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('description', description)
|
||||
@@ -154,6 +203,8 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
if affinity_group is not None and location is not None:
|
||||
raise WindowsAzureError(
|
||||
'Only one of location or affinity_group needs to be specified')
|
||||
if geo_replication_enabled == False:
|
||||
account_type = 'Standard_LRS'
|
||||
return self._perform_post(
|
||||
self._get_storage_service_path(),
|
||||
_XmlSerializer.create_storage_service_input_to_xml(
|
||||
@@ -162,13 +213,14 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
label,
|
||||
affinity_group,
|
||||
location,
|
||||
geo_replication_enabled,
|
||||
account_type,
|
||||
extended_properties),
|
||||
async=True)
|
||||
|
||||
def update_storage_account(self, service_name, description=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
|
||||
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
|
||||
account for your tracking purposes.
|
||||
geo_replication_enabled:
|
||||
Specifies whether the storage account is created with the
|
||||
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.
|
||||
Deprecated. Replaced by the account_type parameter.
|
||||
extended_properties:
|
||||
Dictionary containing name/value pairs of storage account
|
||||
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
|
||||
in the Name, and the name must start with a letter. The value has
|
||||
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)
|
||||
if geo_replication_enabled == False:
|
||||
account_type = 'Standard_LRS'
|
||||
return self._perform_put(
|
||||
self._get_storage_service_path(service_name),
|
||||
_XmlSerializer.update_storage_service_input_to_xml(
|
||||
description,
|
||||
label,
|
||||
geo_replication_enabled,
|
||||
account_type,
|
||||
extended_properties))
|
||||
|
||||
def delete_storage_account(self, service_name):
|
||||
@@ -697,6 +752,50 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
'',
|
||||
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):
|
||||
'''
|
||||
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 + '',
|
||||
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 -----------------------------------
|
||||
def get_role(self, service_name, deployment_name, role_name):
|
||||
'''
|
||||
@@ -1004,7 +1150,13 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
data_virtual_hard_disks=None,
|
||||
role_size=None,
|
||||
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.
|
||||
|
||||
@@ -1025,7 +1177,8 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
WindowsConfigurationSet or LinuxConfigurationSet.
|
||||
os_virtual_hard_disk:
|
||||
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:
|
||||
Encapsulates the metadata required to create the virtual network
|
||||
configuration for a virtual machine. If you do not include a
|
||||
@@ -1053,14 +1206,36 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
virtual_network_name:
|
||||
Specifies the name of an existing virtual network to which the
|
||||
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('deployment_name', deployment_name)
|
||||
_validate_not_none('deployment_slot', deployment_slot)
|
||||
_validate_not_none('label', label)
|
||||
_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(
|
||||
self._get_deployment_path_using_name(service_name),
|
||||
_XmlSerializer.virtual_machine_deployment_to_xml(
|
||||
@@ -1075,13 +1250,22 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
availability_set_name,
|
||||
data_virtual_hard_disks,
|
||||
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)
|
||||
|
||||
def add_role(self, service_name, deployment_name, role_name, system_config,
|
||||
os_virtual_hard_disk, network_config=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.
|
||||
|
||||
@@ -1094,7 +1278,8 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
WindowsConfigurationSet or LinuxConfigurationSet.
|
||||
os_virtual_hard_disk:
|
||||
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:
|
||||
Encapsulates the metadata required to create the virtual network
|
||||
configuration for a virtual machine. If you do not include a
|
||||
@@ -1119,12 +1304,26 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
role_type:
|
||||
The type of the role for the virtual machine. The only supported
|
||||
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('deployment_name', deployment_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(
|
||||
self._get_role_path(service_name, deployment_name),
|
||||
_XmlSerializer.add_role_to_xml(
|
||||
@@ -1135,13 +1334,19 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
network_config,
|
||||
availability_set_name,
|
||||
data_virtual_hard_disks,
|
||||
role_size),
|
||||
role_size,
|
||||
resource_extension_references,
|
||||
provision_guest_agent,
|
||||
vm_image_name,
|
||||
media_location),
|
||||
async=True)
|
||||
|
||||
def update_role(self, service_name, deployment_name, role_name,
|
||||
os_virtual_hard_disk=None, network_config=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.
|
||||
|
||||
@@ -1175,6 +1380,14 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
role_type:
|
||||
The type of the role for the virtual machine. The only supported
|
||||
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('deployment_name', deployment_name)
|
||||
@@ -1188,7 +1401,9 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
network_config,
|
||||
availability_set_name,
|
||||
data_virtual_hard_disks,
|
||||
role_size),
|
||||
role_size,
|
||||
resource_extension_references,
|
||||
provision_guest_agent),
|
||||
async=True)
|
||||
|
||||
def delete_role(self, service_name, deployment_name, role_name):
|
||||
@@ -1354,7 +1569,307 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
role_names, post_shutdown_action),
|
||||
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 -----------------------------
|
||||
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):
|
||||
'''
|
||||
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)
|
||||
|
||||
#--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):
|
||||
return self._get_path('services/networking/virtualnetwork', None)
|
||||
|
||||
@@ -1741,6 +2262,31 @@ class ServiceManagementService(_ServiceManagementClient):
|
||||
'/deployments/' + deployment_name +
|
||||
'/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,
|
||||
lun=None):
|
||||
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
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
import hashlib
|
||||
import hmac
|
||||
import sys
|
||||
import types
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil import parser
|
||||
from dateutil.tz import tzutc
|
||||
from xml.dom import minidom
|
||||
from azure import (WindowsAzureData,
|
||||
WindowsAzureError,
|
||||
@@ -36,6 +36,7 @@ from azure import (WindowsAzureData,
|
||||
_general_error_handler,
|
||||
_list_of,
|
||||
_parse_response_for_dict,
|
||||
_sign_string,
|
||||
_unicode_type,
|
||||
_ERROR_CANNOT_SERIALIZE_VALUE_TO_ENTITY,
|
||||
)
|
||||
@@ -408,7 +409,7 @@ def _update_storage_header(request):
|
||||
if request.body:
|
||||
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']:
|
||||
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
|
||||
|
||||
|
||||
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):
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
@@ -572,7 +562,12 @@ def _to_entity_bool(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):
|
||||
@@ -607,12 +602,9 @@ def _from_entity_int(value):
|
||||
|
||||
|
||||
def _from_entity_datetime(value):
|
||||
format = '%Y-%m-%dT%H:%M:%S'
|
||||
if '.' in value:
|
||||
format = format + '.%f'
|
||||
if value.endswith('Z'):
|
||||
format = format + 'Z'
|
||||
return datetime.strptime(value, format)
|
||||
# Note that Azure always returns UTC datetime, and dateutil parser
|
||||
# will set the tzinfo on the date it returns
|
||||
return parser.parse(value)
|
||||
|
||||
_ENTITY_TO_PYTHON_CONVERSIONS = {
|
||||
'Edm.Binary': _from_entity_binary,
|
||||
@@ -705,7 +697,7 @@ def _convert_entity_to_xml(source):
|
||||
|
||||
if sys.version_info < (3,):
|
||||
if isinstance(properties_str, unicode):
|
||||
properties_str = properties_str.encode(encoding='utf-8')
|
||||
properties_str = properties_str.encode('utf-8')
|
||||
|
||||
# generate the entity_body
|
||||
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
|
||||
for xml_property in xml_properties[0].childNodes:
|
||||
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:
|
||||
value = xml_property.firstChild.nodeValue
|
||||
|
||||
@@ -62,6 +62,7 @@ else:
|
||||
# Keep this value sync with _ERROR_PAGE_BLOB_SIZE_ALIGNMENT
|
||||
_PAGE_SIZE = 512
|
||||
|
||||
|
||||
class BlobService(_StorageClient):
|
||||
|
||||
'''
|
||||
@@ -101,6 +102,7 @@ class BlobService(_StorageClient):
|
||||
Live host base url. If not specified, uses the host base specified
|
||||
when BlobService was initialized.
|
||||
'''
|
||||
|
||||
if not account_name:
|
||||
account_name = self.account_name
|
||||
if not protocol:
|
||||
@@ -553,6 +555,7 @@ class BlobService(_StorageClient):
|
||||
request, self.use_local_storage)
|
||||
request.headers = _update_storage_blob_header(
|
||||
request, self.account_name, self.account_key)
|
||||
|
||||
response = self._perform_request(request)
|
||||
|
||||
return _parse_response_for_dict(response)
|
||||
@@ -740,26 +743,6 @@ class BlobService(_StorageClient):
|
||||
_validate_not_none('container_name', container_name)
|
||||
_validate_not_none('blob_name', blob_name)
|
||||
_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)
|
||||
with open(file_path, 'rb') as stream:
|
||||
@@ -833,26 +816,6 @@ class BlobService(_StorageClient):
|
||||
_validate_not_none('container_name', container_name)
|
||||
_validate_not_none('blob_name', blob_name)
|
||||
_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 progress_callback:
|
||||
@@ -922,7 +885,14 @@ class BlobService(_StorageClient):
|
||||
else:
|
||||
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,
|
||||
index=0, count=None, content_encoding=None,
|
||||
@@ -980,26 +950,6 @@ class BlobService(_StorageClient):
|
||||
_validate_not_none('blob', blob)
|
||||
_validate_not_none('index', index)
|
||||
_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:
|
||||
raise TypeError(_ERROR_VALUE_NEGATIVE.format('index'))
|
||||
@@ -1101,26 +1051,6 @@ class BlobService(_StorageClient):
|
||||
_validate_not_none('container_name', container_name)
|
||||
_validate_not_none('blob_name', blob_name)
|
||||
_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):
|
||||
_validate_not_none('text_encoding', text_encoding)
|
||||
@@ -1541,7 +1471,7 @@ class BlobService(_StorageClient):
|
||||
|
||||
index = 0
|
||||
while index < blob_size:
|
||||
chunk_range = 'bytes={}-{}'.format(
|
||||
chunk_range = 'bytes={0}-{1}'.format(
|
||||
index,
|
||||
index + self._BLOB_MAX_CHUNK_DATA_SIZE - 1)
|
||||
data = self.get_blob(
|
||||
@@ -1862,6 +1792,7 @@ class BlobService(_StorageClient):
|
||||
('x-ms-lease-id', _str_or_none(x_ms_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, self.use_local_storage)
|
||||
request.headers = _update_storage_blob_header(
|
||||
@@ -1904,7 +1835,8 @@ class BlobService(_StorageClient):
|
||||
self._perform_request(request)
|
||||
|
||||
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
|
||||
deleted during garbage collection.
|
||||
@@ -1917,7 +1849,22 @@ class BlobService(_StorageClient):
|
||||
snapshot:
|
||||
Optional. The snapshot parameter is an opaque DateTime value that,
|
||||
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_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('blob_name', blob_name)
|
||||
@@ -1925,8 +1872,14 @@ class BlobService(_StorageClient):
|
||||
request.method = 'DELETE'
|
||||
request.host = self._get_host()
|
||||
request.path = '/' + _str(container_name) + '/' + _str(blob_name) + ''
|
||||
request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))]
|
||||
request.query = [('snapshot', _str_or_none(snapshot))]
|
||||
request.headers = [
|
||||
('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, self.use_local_storage)
|
||||
request.headers = _update_storage_blob_header(
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#--------------------------------------------------------------------------
|
||||
from azure import url_quote
|
||||
from azure.storage import _sign_string, X_MS_VERSION
|
||||
from azure import _sign_string, url_quote
|
||||
from azure.storage import X_MS_VERSION
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Constants for the share access signature
|
||||
SIGNED_VERSION = 'sv'
|
||||
SIGNED_START = 'st'
|
||||
SIGNED_EXPIRY = 'se'
|
||||
SIGNED_RESOURCE = 'sr'
|
||||
|
||||
Reference in New Issue
Block a user