@ -27,64 +27,59 @@ description:
options :
resource_group :
description :
- " Name of a resource group where the managed disk exists or will be created. "
- Name of a resource group where the managed disk exists or will be created .
required : true
name :
description :
- Name of the managed disk
- Name of the managed disk .
required : true
state :
description :
- Assert the state of the managed disk . Use ' present ' to create or update a managed disk and
' absent ' to delete a managed disk .
- Assert the state of the managed disk . Use C ( present ) to create or update a managed disk and ' absent ' to delete a managed disk .
default : present
choices :
- absent
- present
required : false
location :
description :
- Valid Azure location . Defaults to location of the resource group .
default : resource_group location
required : false
storage_account_type :
description :
- " Type of storage for the managed disk: ' Standard_LRS ' or ' Premium_LRS ' . If not specified the disk is created ' Standard_LRS ' "
- " Type of storage for the managed disk: C(Standard_LRS) or C(Premium_LRS). If not specified the disk is created C(Standard_LRS). "
choices :
- Standard_LRS
- Premium_LRS
required : false
create_option :
description :
- " Allowed values: empty, import, copy. ' import ' from a VHD file in ' source_uri ' and ' copy ' from previous managed disk ' source_resource_uri ' ."
- " Allowed values: empty, import, copy. C(import) from a VHD file in I(source_uri) and C(copy) from previous managed disk I(source_resource_uri) ."
choices :
- empty
- import
- copy
required : false
source_uri :
description :
- URI to a valid VHD file to be used when ' create_option ' is ' import ' .
required : false
- URI to a valid VHD file to be used when I ( create_option ) is C ( import ) .
source_resource_uri :
description :
- The resource ID of the managed disk to copy when ' create_option ' is ' copy ' .
required : false
- The resource ID of the managed disk to copy when I ( create_option ) is C ( copy ) .
os_type :
description :
- " Type of Operating System: ' linux ' or ' windows ' . Used when ' create_option ' is either ' copy ' or ' import ' and the source is an OS disk."
- " Type of Operating System: C(linux) or C(windows). Used when I(create_option) is either C(copy) or C(import) and the source is an OS disk."
choices :
- linux
- windows
required : false
disk_size_gb :
description :
- Size in GB of the managed disk to be created . If ' create_option ' is ' copy ' then the value must be greater than or equal to the source ' s size.
required : true
- Size in GB of the managed disk to be created . If I ( create_option ) is C ( copy ) then the value must be greater than or equal to the source ' s size.
managed_by :
description :
- Name of an existing virtual machine with which the disk is or will be associated , this VM should be in the same resource group .
- To detach a disk from a vm , keep undefined .
version_added : 2.5
tags :
description :
- Tags to assign to the managed disk .
required : false
extends_documentation_fragment :
- azure
@ -101,6 +96,21 @@ EXAMPLES = '''
resource_group : Testing
disk_size_gb : 4
- name : Mount the managed disk to VM
azure_rm_managed_disk :
name : mymanageddisk
location : eastus
resource_group : Testing
disk_size_gb : 4
managed_by : testvm001
- name : Unmount the managed disk to VM
azure_rm_managed_disk :
name : mymanageddisk
location : eastus
resource_group : Testing
disk_size_gb : 4
- name : Delete managed disk
azure_rm_manage_disk :
name : mymanageddisk
@ -129,9 +139,9 @@ import re
from ansible . module_utils . azure_rm_common import AzureRMModuleBase
try :
from msrestazure . tools import parse_resource_id
from msrestazure . azure_exceptions import CloudError
from azure . mgmt . compute . models import DiskCreateOption
from azure . mgmt . compute . models import DiskSku
from azure . mgmt . compute . models import DiskCreateOption , DiskCreateOptionTypes , ManagedDiskParameters , DiskSku , DataDisk
except ImportError :
# This is handled in azure_rm_common
pass
@ -148,7 +158,8 @@ def managed_disk_to_dict(managed_disk):
tags = managed_disk . tags ,
disk_size_gb = managed_disk . disk_size_gb ,
os_type = os_type ,
storage_account_type = ' Premium_LRS ' if managed_disk . sku . tier == ' Premium ' else ' Standard_LRS '
storage_account_type = managed_disk . sku . name . value ,
managed_by = managed_disk . managed_by
)
@ -167,46 +178,41 @@ class AzureRMManagedDisk(AzureRMModuleBase):
) ,
state = dict (
type = ' str ' ,
required = False ,
default = ' present ' ,
choices = [ ' present ' , ' absent ' ]
) ,
location = dict (
type = ' str ' ,
required = False
type = ' str '
) ,
storage_account_type = dict (
type = ' str ' ,
required = False ,
choices = [ ' Standard_LRS ' , ' Premium_LRS ' ]
) ,
create_option = dict (
type = ' str ' ,
required = False ,
choices = [ ' empty ' , ' import ' , ' copy ' ]
) ,
source_uri = dict (
type = ' str ' ,
required = False
type = ' str '
) ,
source_resource_uri = dict (
type = ' str ' ,
required = False
type = ' str '
) ,
os_type = dict (
type = ' str ' ,
required = False ,
choices = [ ' linux ' , ' windows ' ]
) ,
disk_size_gb = dict (
type = ' int ' ,
required = False
type = ' int '
) ,
managed_by = dict (
type = ' str '
)
)
required_if = [
( ' create_option ' , ' import ' , [ ' source_uri ' ] ) ,
( ' create_option ' , ' copy ' , [ ' source_resource_uri ' ] ) ,
( ' state' , ' present ' , [ ' disk_size_gb ' ] )
( ' create_option' , ' empty ' , [ ' disk_size_gb ' ] )
]
self . results = dict (
changed = False ,
@ -222,6 +228,7 @@ class AzureRMManagedDisk(AzureRMModuleBase):
self . os_type = None
self . disk_size_gb = None
self . tags = None
self . managed_by = None
super ( AzureRMManagedDisk , self ) . __init__ (
derived_arg_spec = self . module_arg_spec ,
required_if = required_if ,
@ -232,21 +239,83 @@ class AzureRMManagedDisk(AzureRMModuleBase):
""" Main module execution method """
for key in list ( self . module_arg_spec . keys ( ) ) + [ ' tags ' ] :
setattr ( self , key , kwargs [ key ] )
results = dict ( )
res ource_group = None
response = Non e
res ult = None
changed = Fals e
resource_group = self . get_resource_group ( self . resource_group )
if not self . location :
self . location = resource_group . location
disk_instance = self . get_managed_disk ( )
result = disk_instance
# need create or update
if self . state == ' present ' :
self . results [ ' state ' ] = self . create_or_update_managed_disk ( )
elif self . state == ' absent ' :
self . delete_managed_disk ( )
parameter = self . generate_managed_disk_property ( )
if not disk_instance or self . is_different ( disk_instance , parameter ) :
changed = True
if not self . check_mode :
result = self . create_or_update_managed_disk ( parameter )
else :
result = True
# unmount from the old virtual machine and mount to the new virtual machine
vm_name = parse_resource_id ( disk_instance . get ( ' managed_by ' , ' ' ) ) . get ( ' name ' ) if disk_instance else None
if self . managed_by != vm_name :
changed = True
if not self . check_mode :
if vm_name :
self . detach ( vm_name , result )
if self . managed_by :
self . attach ( self . managed_by , result )
result = self . get_managed_disk ( )
if self . state == ' absent ' and disk_instance :
changed = True
if not self . check_mode :
self . delete_managed_disk ( )
result = True
self . results [ ' changed ' ] = changed
self . results [ ' state ' ] = result
return self . results
def create_or_update_managed_disk ( self ) :
# Scaffolding empty managed disk
def attach ( self , vm_name , disk ) :
vm = self . _get_vm ( vm_name )
# find the lun
luns = ( [ d . lun for d in vm . storage_profile . data_disks ]
if vm . storage_profile . data_disks else [ ] )
lun = max ( luns ) + 1 if luns else 0
# prepare the data disk
params = ManagedDiskParameters ( id = disk . get ( ' id ' ) , storage_account_type = disk . get ( ' storage_account_type ' ) )
data_disk = DataDisk ( lun , DiskCreateOptionTypes . attach , managed_disk = params )
vm . storage_profile . data_disks . append ( data_disk )
self . _update_vm ( vm_name , vm )
def detach ( self , vm_name , disk ) :
vm = self . _get_vm ( vm_name )
leftovers = [ d for d in vm . storage_profile . data_disks if d . name . lower ( ) != disk . get ( ' name ' ) . lower ( ) ]
if len ( vm . storage_profile . data_disks ) == len ( leftovers ) :
self . fail ( " No disk with the name ' {0} ' was found " . format ( disk . get ( ' name ' ) ) )
vm . storage_profile . data_disks = leftovers
self . _update_vm ( vm_name , vm )
def _update_vm ( self , name , params ) :
try :
poller = self . compute_client . virtual_machines . create_or_update ( self . resource_group , name , params )
self . get_poller_result ( poller )
except Exception as exc :
self . fail ( " Error updating virtual machine {0} - {1} " . format ( name , str ( exc ) ) )
def _get_vm ( self , name ) :
try :
return self . compute_client . virtual_machines . get ( self . resource_group , name , expand = ' instanceview ' )
except Exception as exc :
self . fail ( " Error getting virtual machine {0} - {1} " . format ( name , str ( exc ) ) )
def generate_managed_disk_property ( self ) :
disk_params = { }
creation_data = { }
disk_params [ ' location ' ] = self . location
@ -263,26 +332,19 @@ class AzureRMManagedDisk(AzureRMModuleBase):
elif self . create_option == ' copy ' :
creation_data [ ' create_option ' ] = DiskCreateOption . copy
creation_data [ ' source_resource_id ' ] = self . source_resource_uri
disk_params [ ' creation_data ' ] = creation_data
return disk_params
def create_or_update_managed_disk ( self , parameter ) :
try :
# CreationData cannot be changed after creation
disk_params [ ' creation_data ' ] = creation_data
found_prev_disk = self . get_managed_disk ( )
if found_prev_disk :
if not self . is_different ( found_prev_disk , disk_params ) :
return found_prev_disk
if not self . check_mode :
poller = self . compute_client . disks . create_or_update (
self . resource_group ,
self . name ,
disk_params )
aux = self . get_poller_result ( poller )
result = managed_disk_to_dict ( aux )
else :
result = True
self . results [ ' changed ' ] = True
poller = self . compute_client . disks . create_or_update (
self . resource_group ,
self . name ,
parameter )
aux = self . get_poller_result ( poller )
return managed_disk_to_dict ( aux )
except CloudError as e :
self . fail ( " Error creating the managed disk: {0} " . format ( str ( e ) ) )
return result
# This method accounts for the difference in structure between the
# Azure retrieved disk and the parameters for the new disk to be created.
@ -302,30 +364,21 @@ class AzureRMManagedDisk(AzureRMModuleBase):
def delete_managed_disk ( self ) :
try :
if not self . check_mode :
poller = self . compute_client . disks . delete (
self . resource_group ,
self . name )
result = self . get_poller_result ( poller )
else :
result = True
self . results [ ' changed ' ] = True
poller = self . compute_client . disks . delete (
self . resource_group ,
self . name )
return self . get_poller_result ( poller )
except CloudError as e :
self . fail ( " Error deleting the managed disk: {0} " . format ( str ( e ) ) )
return result
def get_managed_disk ( self ) :
resp = False
try :
resp = self . compute_client . disks . get (
self . resource_group ,
self . name )
return managed_disk_to_dict ( resp )
except CloudError as e :
self . log ( ' Did not find managed disk ' )
if resp :
resp = managed_disk_to_dict (
resp )
return resp
def main ( ) :