def __init__(self, resource_group=None, load_balancer_name=None, api_version=constants.API_VER_NETWORK, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) load_balancer_name = load_balancer_name or \ utils.get_resource_name_ref( constants.REL_CONTAINED_IN_LB, 'load_balancer_name', _ctx=_ctx) Resource.__init__( self, 'Backend Address Pool', '/{0}/{1}/{2}/{3}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Network', 'loadBalancers/{0}'.format(load_balancer_name), 'backendAddressPools' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, api_version=constants.API_VER_STORAGE, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) Resource.__init__( self, 'Storage Account', '/{0}/{1}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Storage/storageAccounts' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, api_version=constants.API_VER_NETWORK, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) Resource.__init__( self, 'Public IP Address', '/{0}/{1}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Network/publicIPAddresses' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, api_version=constants.API_VER_COMPUTE, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) Resource.__init__( self, 'Availability Set', '/{0}/{1}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Compute/availabilitySets' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, api_version=constants.API_VER_COMPUTE, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) Resource.__init__( self, 'Virtual Machine', '/{0}/{1}/{2}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Compute', 'virtualMachines' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, virtual_machine=None, api_version=constants.API_VER_COMPUTE, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) virtual_machine = virtual_machine or \ utils.get_rel_node_name(constants.REL_VMX_CONTAINED_IN_VM) Resource.__init__( self, 'Virtual Machine Extension', '/{0}/{1}/{2}/{3}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Compute', 'virtualMachines/{0}'.format(virtual_machine), 'extensions' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, network_interface_card=None, api_version=constants.API_VER_NETWORK, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) network_interface_card = network_interface_card or \ _ctx.node.properties.get('network_interface_card_name') Resource.__init__( self, 'IP Configuration', '/{0}/{1}/{2}/{3}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Network/', 'networkInterfaces/{0}'.format(network_interface_card), 'ipConfigurations' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, network_security_group=None, api_version=constants.API_VER_NETWORK, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) network_security_group = network_security_group or \ utils.get_network_security_group(_ctx=_ctx) Resource.__init__( self, 'Network Security Rule', '/{0}/{1}/{2}/{3}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Network', 'networkSecurityGroups/{0}'.format(network_security_group), 'securityRules' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, virtual_network=None, api_version=constants.API_VER_NETWORK, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) virtual_network = virtual_network or \ utils.get_virtual_network(_ctx=_ctx) Resource.__init__( self, 'Subnet', '/{0}/{1}/{2}/{3}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Network', 'virtualNetworks/{0}'.format(virtual_network), 'subnets' ), api_version=api_version, logger=logger, _ctx=_ctx)
def __init__(self, resource_group=None, load_balancer_name=None, api_version=constants.API_VER_NETWORK, logger=None, _ctx=ctx): resource_group = resource_group or \ utils.get_resource_group(_ctx=_ctx) load_balancer_name = load_balancer_name or \ utils.get_resource_name_ref( constants.REL_CONTAINED_IN_LB, 'load_balancer_name', _ctx=_ctx) Resource.__init__(self, 'Inbound NAT Rule', '/{0}/{1}/{2}/{3}'.format( 'resourceGroups/{0}'.format(resource_group), 'providers/Microsoft.Network', 'loadBalancers/{0}'.format(load_balancer_name), 'inboundNatRules'), api_version=api_version, logger=logger, _ctx=_ctx)
def create(ctx, **_): """Uses an existing, or creates a new, Route Table""" # Create a resource (if necessary) azure_config = ctx.node.properties.get('azure_config') if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated please use client_config, " "in later version it will be removed") name = utils.get_resource_name(ctx) resource_group_name = utils.get_resource_group(ctx) rtbl_params = { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), } rtbl_params = \ utils.handle_resource_config_params(rtbl_params, ctx.node.properties.get( 'resource_config', {})) api_version = \ ctx.node.properties.get('api_version', constants.API_VER_NETWORK) route_table = RouteTable(azure_config, ctx.logger, api_version) # clean empty values from params rtbl_params = \ utils.cleanup_empty_params(rtbl_params) try: result = \ route_table.create_or_update(resource_group_name, name, rtbl_params) except CloudError as cr: raise cfy_exc.NonRecoverableError( "create route_table '{0}' " "failed with this error : {1}".format(name, cr.message)) ctx.instance.runtime_properties['resource_group'] = resource_group_name ctx.instance.runtime_properties['resource'] = result ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
def get_cloud_storage_account(_ctx=ctx): """Gets the Azure Blob storage service""" # Get the storage account storage_account = utils.get_parent(_ctx.instance, rel_type=constants.REL_CONTAINED_IN_SA) resource_group_name = utils.get_resource_group(_ctx) storage_account_name = utils.get_resource_name(_ctx=storage_account) azure_config = _ctx.node.properties.get("azure_config") if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated please use client_config, " "in later version it will be removed") # Get the storage account keys keys = StorageAccount(azure_config, _ctx.logger).list_keys(resource_group_name, storage_account_name) if not keys or not keys.get("key1"): raise RecoverableError( 'StorageAccount reported no usable authentication keys') # Get an interface to the Storage Account storage_account_key = keys.get("key1") return CloudStorageAccount(account_name=storage_account_name, account_key=storage_account_key)
def delete_incoming_nat_rule(ctx, **_): """Deletes a Load Balancer Incoming NAT Rule""" if ctx.node.properties.get('use_external_resource', False): return # Get an interface to the Load Balancer azure_config = ctx.node.properties.get('azure_config') if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated please use client_config, " "in later version it will be removed") resource_group_name = utils.get_resource_group(ctx) lb_rel = utils.get_relationship_by_type( ctx.instance.relationships, constants.REL_CONTAINED_IN_LB) lb_name = utils.get_resource_name(lb_rel.target) load_balancer = LoadBalancer(azure_config, ctx.logger) name = ctx.instance.runtime_properties.get('name') # Get the existing probes lb_data = load_balancer.get(resource_group_name, lb_name) lb_rules = lb_data.get('inbound_nat_rules', list()) for idx, rule in enumerate(lb_rules): if rule.get('name') == name: del lb_rules[idx] # Update the Load Balancer with the new NAT rule list lb_params = { 'inbound_nat_rules': lb_rules } try: load_balancer.create_or_update(resource_group_name, lb_name, lb_params) except CloudError as cr: raise cfy_exc.NonRecoverableError( "delete incoming_nat_rule '{0}' " "failed with this error : {1}".format(name, cr.message) )
def configure(ctx, **_): """ Uses an existing, or creates a new, Network Interface Card .. warning:: The "configure" operation is actually the second half of the "create" operation. This is necessary since IP Configuration nodes are treated as separate, stand-alone types and must be "connected" to the NIC before it's actually created. The actual "create" operation simply assigns a UUID for the node and the "configure" operation creates the object """ # Create a resource (if necessary) azure_config = ctx.node.properties.get('azure_config') if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated please use client_config, " "in later version it will be removed") name = ctx.instance.runtime_properties.get('name') resource_group_name = utils.get_resource_group(ctx) api_version = \ ctx.node.properties.get('api_version', constants.API_VER_NETWORK) network_interface_card = NetworkInterfaceCard(azure_config, ctx.logger, api_version) nic_params = { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'primary': ctx.node.properties.get('primary'), } nic_params = \ utils.handle_resource_config_params(nic_params, ctx.node.properties.get( 'resource_config', {})) # Special Case network_security_group instead of networkSecurityGroups nic_params['network_security_group'] = \ nic_params.pop('network_security_groups', None) # clean empty values from params nic_params = \ utils.cleanup_empty_params(nic_params) nic_params = utils.dict_update( nic_params, { 'network_security_group': get_connected_nsg(ctx), 'ip_configurations': get_ip_configurations(ctx) }) # clean empty values from params nic_params = \ utils.cleanup_empty_params(nic_params) try: result = \ network_interface_card.create_or_update( resource_group_name, name, nic_params) except CloudError as cr: raise cfy_exc.NonRecoverableError( "configure nic '{0}' " "failed with this error : {1}".format(name, cr.message)) ctx.instance.runtime_properties['resource_group'] = resource_group_name ctx.instance.runtime_properties['resource'] = result ctx.instance.runtime_properties['resource_id'] = result.get("id", "") ctx.instance.runtime_properties['name'] = name
def create_rule(ctx, **_): """Uses an existing, or creates a new, Load Balancer Rule""" # Check if invalid external resource if ctx.node.properties.get('use_external_resource', False) and \ not ctx.node.properties.get('name'): raise cfy_exc.NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Generate a name if it doesn't exist azure_config = ctx.node.properties.get('azure_config') if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated please use client_config, " "in later version it will be removed") resource_group_name = utils.get_resource_group(ctx) load_balancer_name = ctx.node.properties.get('load_balancer_name') or \ utils.get_resource_name_ref(constants.REL_CONTAINED_IN_LB, 'load_balancer_name', _ctx=ctx) load_balancer = LoadBalancer(azure_config, ctx.logger) lb_rule_name = ctx.node.properties.get('name') lb_rule_name = \ get_unique_lb_prop_name(load_balancer, resource_group_name, load_balancer_name, "load_balancing_rules", lb_rule_name) ctx.instance.runtime_properties['name'] = lb_rule_name # Get an interface to the Load Balancer lb_rel = utils.get_relationship_by_type( ctx.instance.relationships, constants.REL_CONTAINED_IN_LB) lb_name = utils.get_resource_name(lb_rel.target) load_balancer = LoadBalancer(azure_config, ctx.logger) lb_data = load_balancer.get(resource_group_name, lb_name) # Get the Load Balancer Backend Pool/ Probe/ Frontend IP Configuration lb_be_pool_id = "" lb_probe_id = "" lb_fe_ipc_id = "" rel_pool_type = constants.REL_CONNECTED_TO_LB_BE_POOL rel_probe_type = constants.REL_CONNECTED_TO_LB_PROBE rel_fe_type = constants.REL_CONNECTED_TO_IPC for rel in ctx.instance.relationships: if isinstance(rel_pool_type, tuple): if any(x in rel.type_hierarchy for x in rel_pool_type): lb_be_pool_id = \ rel.target.instance.runtime_properties.get('resource_id') else: if rel_pool_type in rel.type_hierarchy: lb_be_pool_id = \ rel.target.instance.runtime_properties.get('resource_id') if isinstance(rel_probe_type, tuple): if any(x in rel.type_hierarchy for x in rel_probe_type): lb_probe_id = \ rel.target.instance.runtime_properties.get('resource_id') else: if constants.REL_CONNECTED_TO_LB_PROBE in rel.type_hierarchy: lb_probe_id = \ rel.target.instance.runtime_properties.get('resource_id') if isinstance(rel_fe_type, tuple): if any(x in rel.type_hierarchy for x in rel_fe_type): lb_fe_ipc_id = \ rel.target.instance.runtime_properties.get('resource_id') else: if constants.REL_CONNECTED_TO_IPC in rel.type_hierarchy: lb_fe_ipc_id = \ rel.target.instance.runtime_properties.get('resource_id') # Get the existing Load Balancer Rules lb_rules = lb_data.get('load_balancing_rules', list()) lb_rules.append({ 'name': lb_rule_name, 'frontend_ip_configuration': {'id': lb_fe_ipc_id}, 'backend_address_pool': {'id': lb_be_pool_id}, 'probe': {'id': lb_probe_id} }) # Update the Load Balancer with the new rule lb_params = { 'load_balancing_rules': lb_rules } # clean empty values from params lb_params = \ utils.cleanup_empty_params(lb_params) try: result = load_balancer.create_or_update(resource_group_name, lb_name, lb_params) for item in result.get("load_balancing_rules"): if item.get("name") == lb_rule_name: ctx.instance.runtime_properties['resource_id'] = item.get("id") ctx.instance.runtime_properties['resource'] = item except CloudError as cr: raise cfy_exc.NonRecoverableError( "create load_balancing_rules '{0}' " "failed with this error : {1}".format(lb_rule_name, cr.message) )
def configure(ctx, **_): """Uses an existing, or creates a new, Load Balancer""" # Get the Frontend IP Configuration fe_ip_cfg = get_ip_configurations(rel=constants.REL_LB_CONNECTED_TO_IPC) ctx.logger.debug('fe_ip_cfg: {0}'.format(fe_ip_cfg)) if not len(fe_ip_cfg): raise cfy_exc.NonRecoverableError( 'At least 1 Frontend IP Configuration must be ' 'associated with the Load Balancer') # Remove the subnet if there's a public IP present for ip_cfg in fe_ip_cfg: if ip_cfg.get('public_ip_address'): if ip_cfg.get('subnet'): del ip_cfg['subnet'] # Create a resource (if necessary) azure_config = ctx.node.properties.get('azure_config') if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated please use client_config, " "in later version it will be removed") name = ctx.instance.runtime_properties.get('name') resource_group_name = utils.get_resource_group(ctx) api_version = \ ctx.node.properties.get('api_version', constants.API_VER_NETWORK) load_balancer = LoadBalancer(azure_config, ctx.logger, api_version) lb_params = { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), } lb_params = \ utils.handle_resource_config_params(lb_params, ctx.node.properties.get( 'resource_config', {})) lb_params = utils.dict_update( lb_params, { 'frontend_ip_configurations': fe_ip_cfg } ) # clean empty values from params lb_params = \ utils.cleanup_empty_params(lb_params) try: result = \ load_balancer.create_or_update(resource_group_name, name, lb_params) except CloudError as cr: raise cfy_exc.NonRecoverableError( "create load_balancer '{0}' " "failed with this error : {1}".format(name, cr.message) ) ctx.instance.runtime_properties['resource_group'] = resource_group_name ctx.instance.runtime_properties['resource'] = result ctx.instance.runtime_properties['resource_id'] = result.get("id", "") ctx.instance.runtime_properties['name'] = name for fe_ipc_data in result.get('frontend_ip_configurations', list()): ctx.instance.runtime_properties['ip'] = \ fe_ipc_data.get('private_ip_address') public_ip = \ fe_ipc_data.get('public_ip_address', {}).get('ip_address', None) if not public_ip: pip = PublicIPAddress(azure_config, ctx.logger) pip_name = \ ip_cfg.get('public_ip_address').get('id').rsplit('/', 1)[1] public_ip_data = pip.get(resource_group_name, pip_name) public_ip = public_ip_data.get("ip_address") ctx.instance.runtime_properties['public_ip'] = public_ip
def wrapper_inner(*args, **kwargs): ctx = kwargs['ctx'] try: # check if name is set or not and generate one if it wasn't set azure_config = ctx.node.properties.get('azure_config') if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated " "please use client_config, " "in later version it will be removed") resource = resource_class_name(azure_config, ctx.logger) name = utils.get_resource_name(ctx) resource_group_name = name if not isinstance(resource, ResourceGroup): resource_group_name = utils.get_resource_group(ctx) if not name: ctx.logger.info("Generating unique name for {0}".format( resource_class_name)) # handle special cases # virtual_machine_extension if isinstance(resource, VirtualMachineExtension): vm_name = \ ctx.node.properties.get('virtual_machine_name') name = get_unique_name( resource=resource, resource_group_name=resource_group_name, name=name, vm_name=vm_name) # subnet elif isinstance(resource, Subnet): vnet_name = utils.get_virtual_network(ctx) name = get_unique_name( resource=resource, resource_group_name=resource_group_name, name=name, vnet_name=vnet_name) # route elif isinstance(resource, Route): rtbl_name = utils.get_route_table(ctx) name = get_unique_name( resource=resource, resource_group_name=resource_group_name, name=name, rtbl_name=rtbl_name) # network_security_rule elif isinstance(resource, NetworkSecurityRule): nsg_name = utils.get_network_security_group(ctx) name = get_unique_name( resource=resource, resource_group_name=resource_group_name, name=name, nsg_name=nsg_name) elif isinstance(resource, Deployment): name = get_unique_name( resource=resource, resource_group_name=resource_group_name, name=name) else: name = get_unique_name( resource=resource, resource_group_name=resource_group_name, name=name) ctx.instance.runtime_properties['name'] = name except CloudError: raise cfy_exc.NonRecoverableError( "Can't generate name for {0}".format(resource_class_name)) return func(*args, **kwargs)
def wrapper_inner(*args, **kwargs): ctx = kwargs['ctx'] name = utils.get_resource_name(ctx) try: # check if azure_config is given and if the resource # is external or not azure_config = ctx.node.properties.get('azure_config') if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated " "please use client_config, " "in later version it will be removed") resource = resource_class_name(azure_config, ctx.logger) if not isinstance(resource, ResourceGroup): resource_group_name = utils.get_resource_group(ctx) # handle speical cases # resource_group if isinstance(resource, ResourceGroup): exists = resource.get(name) elif isinstance(resource, Deployment): exists = resource.get(resource_group_name, name) # virtual_machine_extension elif isinstance(resource, VirtualMachineExtension): vm_name = \ ctx.node.properties.get('virtual_machine_name') exists = resource.get(resource_group_name, vm_name, name) # subnet elif isinstance(resource, Subnet): vnet_name = utils.get_virtual_network(ctx) exists = resource.get(resource_group_name, vnet_name, name) # route elif isinstance(resource, Route): rtbl_name = utils.get_route_table(ctx) exists = resource.get(resource_group_name, rtbl_name, name) # network_security_rule elif isinstance(resource, NetworkSecurityRule): nsg_name = utils.get_network_security_group(ctx) exists = resource.get(resource_group_name, nsg_name, name) else: exists = resource.get(resource_group_name, name) except CloudError: exists = None # There is now a good idea whether the desired resource exists. # Now find out if it is expected and if it does or doesn't. expected = ctx.node.properties.get('use_external_resource', False) create_anyway = ctx.node.properties.get('create_if_missing', False) use_anyway = ctx.node.properties.get('use_if_exists', False) # We should use and existing resource. use_existing = (exists and expected) or \ (exists and not expected and use_anyway) # We should create a new resource. create = (not exists and not expected) or \ (not exists and expected and create_anyway) # ARM deployments are idempotent. This logic should be expanded # to other idempotent deployments. arm_deployment = 'cloudify.azure.Deployment' in \ ctx.node.type_hierarchy create_op = 'create' in ctx.operation.name.split('.')[-1] if not exists and expected and not create_anyway: raise cfy_exc.NonRecoverableError( "Can't use non-existing {0} '{1}'.".format( resource_class_name, name)) elif use_existing and not (create_op and arm_deployment): ctx.logger.info("Using external resource") ctx.instance.runtime_properties['resource'] = exists ctx.instance.runtime_properties['resource_id'] = exists.get( "id", "") return elif not create and not (create_op and arm_deployment): raise cfy_exc.NonRecoverableError( "Can't use non-existing {0} '{1}'.".format( resource_class_name, name)) elif create and exists and ctx.workflow_id not in \ ['update', 'execute_operation']: ctx.logger.warn("Resource with name {0} exists".format(name)) if not arm_deployment: ctx.logger.warn('Not updating new resource.') return ctx.logger.info( 'Creating or updating resource: {name}'.format(name=name)) return func(*args, **kwargs)
def create_file_share(ctx, **_): """Creates an Azure File Share""" # Get resource config values res_cfg = ctx.node.properties.get("resource_config", {}) share_name = utils.get_resource_name(ctx) metadata = res_cfg.get('metadata') quota = res_cfg.get('quota') fail_on_exist = res_cfg.get('fail_on_exist', False) # Check if invalid external resource if ctx.node.properties.get('use_external_resource', False) and \ not share_name: raise NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Get the storage account storage_account = utils.get_parent(ctx.instance, rel_type=constants.REL_CONTAINED_IN_SA) resource_group_name = utils.get_resource_group(ctx) storage_account_name = utils.get_resource_name(_ctx=storage_account) azure_config = ctx.node.properties.get("azure_config") if not azure_config.get("subscription_id"): azure_config = ctx.node.properties.get('client_config') else: ctx.logger.warn("azure_config is deprecated please use client_config, " "in later version it will be removed") # Get the storage account keys keys = StorageAccount(azure_config, ctx.logger).list_keys(resource_group_name, storage_account_name) if not keys or not keys.get("key1"): raise RecoverableError( 'StorageAccount reported no usable authentication keys') # Get an interface to the Storage Account storage_account_key = keys.get("key1") storageacct = CloudStorageAccount(account_name=storage_account_name, account_key=storage_account_key) # Get an interface to the File Service filesvc = storageacct.create_file_service() if ctx.node.properties.get('use_external_resource', False): # Attempt to use an existing File Share (if specified) ctx.logger.debug( 'Checking for existing File Share "{0}"'.format(share_name)) try: share = filesvc.get_share_properties(share_name) metadata = share.get('metadata', dict()) quota = share.get('properties', dict()).get('quota') created = False except Exception as ex: ctx.logger.error( 'File Share "{0}" does not exist and ' '"use_external_resource" is set to true'.format(share_name)) raise NonRecoverableError(ex) else: # Generate a new File Share name if needed if not share_name: ctx.logger.info('Generating a new File Share name') for _ in range(0, 10): tmpname = file_share_name_generator() if not file_share_exists(ctx, filesvc, tmpname): share_name = tmpname break # Handle name error if not share_name: raise NonRecoverableError( 'Error generating a new File Share name. Failed ' 'after 10 tries.') # Attempt to create the File Share ctx.logger.debug('Creating File Share "{0}"'.format(share_name)) created = filesvc.create_share(share_name=share_name, metadata=metadata, quota=quota, fail_on_exist=False) if not created: ctx.logger.warn('File Share already exists') if fail_on_exist: raise NonRecoverableError( 'File Share already exists in the storage account and ' '"fail_on_exist" set to True') # Set run-time properties ctx.instance.runtime_properties['name'] = share_name ctx.instance.runtime_properties['quota'] = quota ctx.instance.runtime_properties['metadata'] = metadata ctx.instance.runtime_properties['created'] = created ctx.instance.runtime_properties['storage_account'] = storage_account_name ctx.instance.runtime_properties['username'] = storage_account_name ctx.instance.runtime_properties['password'] = storage_account_key ctx.instance.runtime_properties['uri'] = '{0}.file.{1}/{2}'.format( storage_account_name, constants.CONN_STORAGE_FILE_ENDPOINT, share_name)
def configure(ctx, command_to_execute, file_uris, type_handler_version='1.8', **_): """Configures the resource""" azure_config = utils.get_client_config(ctx.node.properties) resource_group_name = utils.get_resource_group(ctx) vm_name = utils.get_resource_name(ctx) os_family = ctx.node.properties.get('os_family', '').lower() if os_family == 'windows': vm_extension = VirtualMachineExtension(azure_config, ctx.logger) vm_extension_name = "{0}".format(uuid4()) vm_extension_params = { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'publisher': 'Microsoft.Compute', 'virtual_machine_extension_type': 'CustomScriptExtension', 'type_handler_version': type_handler_version, 'settings': { 'fileUris': file_uris, 'commandToExecute': command_to_execute } } # ctx.logger.info("sending {0}".format(vm_extension_params)) try: result = \ vm_extension.create_or_update(resource_group_name, vm_name, vm_extension_name, vm_extension_params) except CloudError as cr: raise cfy_exc.NonRecoverableError( "configure virtual_machine '{0}' " "failed with this error : {1}".format(vm_name, cr.message) ) ctx.instance.runtime_properties['resource_extension'] = result ctx.instance.runtime_properties['resource_extension_id'] = \ result.get("id", "") ctx.instance.runtime_properties['extension_name'] = vm_extension_name # Write the IP address to runtime properties for the agent # Get a reference to the NIC rel_nics = utils.get_relationships_by_type( ctx.instance.relationships, constants.REL_CONNECTED_TO_NIC) ctx.logger.debug('net_rels: {0}'.format( [net_rel.target.node.id for net_rel in rel_nics])) # No NIC? Exit and hope the user doesn't plan to install an agent if not rel_nics: return vm_id = ctx.instance.runtime_properties.get("resource_id") public_ip_addresses = [] for rel_nic in rel_nics: # Get the NIC data from the API directly (because of IPConfiguration) nic_azure_config = utils.get_client_config( rel_nic.target.node.properties) nic_resource_group = utils.get_resource_group(rel_nic.target) nic_name = utils.get_resource_name(rel_nic.target) nic_iface = NetworkInterfaceCard(nic_azure_config, ctx.logger) nic_data = nic_iface.get(nic_resource_group, nic_name) nic_vm_id = nic_data.get('virtual_machine', {}).get('id') if not nic_vm_id: if not vm_id: nic_data['virtual_machine'] = { 'id': utils.get_resource_id_from_name( azure_config.get('subscription_id'), resource_group_name, 'Microsoft.Compute', 'virtualMachines', vm_name ) } elif vm_id not in nic_vm_id: nic_data['virtual_machine'] = { 'id': vm_id } ctx.logger.info('nic_data {nic_data}'.format(nic_data=nic_data)) nic_data = nic_iface.create_or_update(nic_resource_group, nic_name, nic_data) # Iterate over each IPConfiguration entry for ip_cfg in nic_data.get('ip_configurations', list()): # Get the Private IP Address endpoint private_ip = ip_cfg.get('private_ip_address') ctx.instance.runtime_properties['ip'] = private_ip public_ip = ip_cfg.get('public_ip_address', {}).get('ip_address') if not public_ip: azure_config = utils.get_client_config(ctx.node.properties) resource_group_name = utils.get_resource_group(ctx) pip = PublicIPAddress(azure_config, ctx.logger) pip_cfg = ip_cfg.get('public_ip_address') if pip_cfg: pip_name = pip_cfg.get('id').rsplit('/', 1)[1] public_ip_data = pip.get(resource_group_name, pip_name) public_ip = public_ip_data.get("ip_address") if not public_ip: # skip the public ip from this ip configuration as it is None continue ctx.instance.runtime_properties['public_ip'] = public_ip # For consistency with other plugins. ctx.instance.runtime_properties[PUBLIC_IP_PROPERTY] = public_ip # We should also consider that maybe there will be many # public ip addresses. if public_ip not in public_ip_addresses: public_ip_addresses.append(public_ip) ctx.instance.runtime_properties['public_ip_addresses'] = \ public_ip_addresses # if no public_ip default to private_ip public_ip = ctx.instance.runtime_properties.get('public_ip') if not public_ip: public_ip = ctx.instance.runtime_properties.get('ip') ctx.instance.runtime_properties['public_ip'] = public_ip # See if the user wants to use the public IP as primary IP if ctx.node.properties.get('use_public_ip') and \ ctx.instance.runtime_properties.get('public_ip'): ctx.instance.runtime_properties['ip'] = \ ctx.instance.runtime_properties.get('public_ip') ctx.logger.info('OUTPUT {0}.{1} = "{2}"'.format( ctx.instance.id, 'ip', ctx.instance.runtime_properties.get('ip'))) ctx.logger.info('OUTPUT {0}.{1} = "{2}"'.format( ctx.instance.id, 'public_ip', ctx.instance.runtime_properties.get('public_ip')))
def create(ctx, args=None, **_): """Uses an existing, or creates a new, Virtual Machine""" azure_config = utils.get_client_config(ctx.node.properties) name = utils.get_resource_name(ctx) resource_group_name = utils.get_resource_group(ctx) api_version = \ ctx.node.properties.get('api_version', constants.API_VER_COMPUTE) virtual_machine = VirtualMachine(azure_config, ctx.logger, api_version) res_cfg = ctx.node.properties.get("resource_config", {}) spot_instance = res_cfg.pop("spot_instance", None) # Build storage profile osdisk = build_osdisk_profile(ctx, res_cfg.get( 'storageProfile', dict()).get('osDisk', dict())) datadisks = build_datadisks_profile(ctx, res_cfg.get( 'storageProfile', dict()).get('dataDisks', list())) storage_profile = { 'os_disk': osdisk, 'data_disks': datadisks } # Build the network profile network_profile = build_network_profile(ctx) # Build the OS profile os_family = ctx.node.properties.get('os_family', '').lower() os_profile = dict() # Set defaults for Windows installs to enable WinRM listener if os_family == 'windows' and \ not res_cfg.get('osProfile', dict()).get('windowsConfiguration'): os_profile = { 'windows_configuration': { # This is required for extension scripts to work 'provision_vm_agent': True, 'win_rm': { 'listeners': [{ 'protocol': 'Http', 'certificate_url': None }] } }, 'linux_configuration': None } elif not res_cfg.get('osProfile', dict()).get('linuxConfiguration'): os_profile = { 'linux_configuration': { 'disable_password_authentication': False }, 'windows_configuration': None } # Set the computerName if it's not set already os_profile['computer_name'] = \ res_cfg.get( 'osProfile', dict() ).get('computerName', name) availability_set = None rel_type = constants.REL_CONNECTED_TO_AS for rel in ctx.instance.relationships: if isinstance(rel_type, tuple): if any(x in rel.type_hierarchy for x in rel_type): availability_set = { 'id': rel.target.instance.runtime_properties.get( "resource_id") } else: if rel_type in rel.type_hierarchy: availability_set = { 'id': rel.target.instance.runtime_properties.get( "resource_id") } resource_create_payload = { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'plan': ctx.node.properties.get('plan'), 'availabilitySet': availability_set, 'networkProfile': network_profile, 'storageProfile': storage_profile, 'osProfile': os_profile } # check if spot_instance if spot_instance and spot_instance.get("is_spot_instance"): # this is just an indacator not part of the api spot_instance.pop("is_spot_instance") # handle the params resource_create_payload = \ utils.dict_update(resource_create_payload, spot_instance) resource_create_payload = \ utils.handle_resource_config_params(resource_create_payload, utils.get_resource_config( _ctx=ctx, args=args)) # support userdata from args. os_profile = resource_create_payload['os_profile'] userdata = _handle_userdata(ctx, os_profile.get('custom_data')) if userdata: ctx.logger.warn( 'Azure customData implementation is dependent on ' 'Virtual Machine image support.') resource_create_payload['os_profile']['custom_data'] = \ base64.b64encode(userdata.encode('utf-8')).decode('utf-8') # Remove custom_data from os_profile if empty to avoid Errors. elif 'custom_data' in resource_create_payload['os_profile']: del resource_create_payload['os_profile']['custom_data'] # Create a resource (if necessary) try: result = \ virtual_machine.create_or_update(resource_group_name, name, resource_create_payload) except CloudError as cr: raise cfy_exc.NonRecoverableError( "create virtual_machine '{0}' " "failed with this error : {1}".format(name, cr.message) ) ctx.instance.runtime_properties['resource_group'] = resource_group_name ctx.instance.runtime_properties['resource'] = result ctx.instance.runtime_properties['resource_id'] = result.get("id", "")