def delete_backend_pool(**_): '''Deletes a Load Balancer Backend Pool''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_iface = LoadBalancer( _ctx=lb_rel.target, api_version=ctx.node.properties.get('api_version', constants.API_VER_NETWORK)) # Get the existing pools lb_data = lb_iface.get(lb_name) lb_pools = lb_data.get('properties', dict()).get( 'backendAddressPools', list()) for idx, pool in enumerate(lb_pools): if pool.get('name') == utils.get_resource_name(): del lb_pools[idx] # Update the Load Balancer with the new pool list utils.task_resource_update( lb_iface, { 'properties': { 'backendAddressPools': lb_pools } }, name=lb_name)
def create_probe(**_): '''Uses an existing, or creates a new, Load Balancer Probe''' # Check if invalid external resource if ctx.node.properties.get('use_external_resource', False) and \ not ctx.node.properties.get('name'): raise NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Generate a name if it doesn't exist utils.generate_resource_name( Probe(api_version=ctx.node.properties.get('api_version', constants.API_VER_NETWORK))) # 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) lb_iface = LoadBalancer(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) # Get the existing probes lb_data = lb_iface.get(lb_name) lb_probes = lb_data.get('properties', dict()).get('probes', list()) lb_probes.append({ 'name': utils.get_resource_name(), 'properties': utils.get_resource_config() }) # Update the Load Balancer with the new probe utils.task_resource_update(lb_iface, {'properties': { 'probes': lb_probes }}, name=lb_name)
def delete_incoming_nat_rule(**_): '''Deletes a Load Balancer Incoming NAT Rule''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_iface = LoadBalancer(_ctx=lb_rel.target) # Get the existing probes lb_data = lb_iface.get(lb_name) lb_rules = lb_data.get('properties', dict()).get( 'inboundNatRules', list()) for idx, rule in enumerate(lb_rules): if rule.get('name') == utils.get_resource_name(): del lb_rules[idx] # Update the Load Balancer with the new NAT rule list utils.task_resource_update( lb_iface, { 'properties': { 'inboundNatRules': lb_rules } }, name=lb_name)
def delete_probe(**_): '''Deletes a Load Balancer Probe''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_iface = LoadBalancer(_ctx=lb_rel.target) # Get the existing probes lb_data = lb_iface.get(lb_name) lb_probes = lb_data.get('properties', dict()).get( 'probes', list()) for idx, probe in enumerate(lb_probes): if probe.get('name') == utils.get_resource_name(): del lb_probes[idx] # Update the Load Balancer with the new probes list utils.task_resource_update( lb_iface, { 'properties': { 'probes': lb_probes } }, name=lb_name)
def delete_rule(**_): ''' Deletes a Load Balancer Rule TODO: Rewrite this to occur inside of a Relationship Operation ''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_ctx = utils.get_relationship_subject_ctx(ctx, lb_rel.target) lb_iface = LoadBalancer(_ctx=lb_ctx, api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) # Get the existing rules lb_data = lb_iface.get(lb_name) lb_rules = lb_data.get('properties', dict()).get('loadBalancingRules', list()) for idx, rule in enumerate(lb_rules): if rule.get('name') == utils.get_resource_name(): del lb_rules[idx] # Update the Load Balancer with the new rules list utils.task_resource_update( lb_iface, {'properties': { 'loadBalancingRules': lb_rules }}, name=lb_name)
def create_backend_pool(**_): '''Uses an existing, or creates a new, Load Balancer Backend Pool''' # Check if invalid external resource if ctx.node.properties.get('use_external_resource', False) and \ not ctx.node.properties.get('name'): raise NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Generate a name if it doesn't exist utils.generate_resource_name(BackendAddressPool()) # 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) lb_iface = LoadBalancer() # Get the existing pools lb_data = lb_iface.get(lb_name) lb_pools = lb_data.get('properties', dict()).get( 'backendAddressPools', list()) lb_pools.append({'name': utils.get_resource_name()}) # Update the Load Balancer with the new pool utils.task_resource_update( lb_iface, { 'properties': { 'backendAddressPools': lb_pools } }, name=lb_name)
def delete_backend_pool(**_): '''Deletes a Load Balancer Backend Pool''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_iface = LoadBalancer(_ctx=lb_rel.target) # Get the existing pools lb_data = lb_iface.get(lb_name) lb_pools = lb_data.get('properties', dict()).get( 'backendAddressPools', list()) for idx, pool in enumerate(lb_pools): if pool.get('name') == utils.get_resource_name(): del lb_pools[idx] # Update the Load Balancer with the new pool list utils.task_resource_update( lb_iface, { 'properties': { 'backendAddressPools': lb_pools } }, name=lb_name)
def create_probe(**_): '''Uses an existing, or creates a new, Load Balancer Probe''' # Check if invalid external resource if ctx.node.properties.get('use_external_resource', False) and \ not ctx.node.properties.get('name'): raise NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Generate a name if it doesn't exist utils.generate_resource_name(Probe(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK))) # 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) lb_iface = LoadBalancer(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) # Get the existing probes lb_data = lb_iface.get(lb_name) lb_probes = lb_data.get('properties', dict()).get( 'probes', list()) lb_probes.append({ 'name': utils.get_resource_name(), 'properties': utils.get_resource_config() }) # Update the Load Balancer with the new probe utils.task_resource_update( lb_iface, { 'properties': { 'probes': lb_probes } }, name=lb_name)
def delete_incoming_nat_rule(**_): '''Deletes a Load Balancer Incoming NAT Rule''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_iface = LoadBalancer( _ctx=lb_rel.target, api_version=ctx.node.properties.get('api_version', constants.API_VER_NETWORK)) # Get the existing probes lb_data = lb_iface.get(lb_name) lb_rules = lb_data.get('properties', dict()).get( 'inboundNatRules', list()) for idx, rule in enumerate(lb_rules): if rule.get('name') == utils.get_resource_name(): del lb_rules[idx] # Update the Load Balancer with the new NAT rule list utils.task_resource_update( lb_iface, { 'properties': { 'inboundNatRules': lb_rules } }, name=lb_name)
def delete_rule(**_): ''' Deletes a Load Balancer Rule TODO: Rewrite this to occur inside of a Relationship Operation ''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_ctx = utils.get_relationship_subject_ctx(ctx, lb_rel.target) lb_iface = LoadBalancer(_ctx=lb_ctx, api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) # Get the existing rules lb_data = lb_iface.get(lb_name) lb_rules = lb_data.get('properties', dict()).get( 'loadBalancingRules', list()) for idx, rule in enumerate(lb_rules): if rule.get('name') == utils.get_resource_name(): del lb_rules[idx] # Update the Load Balancer with the new rules list utils.task_resource_update( lb_iface, { 'properties': { 'loadBalancingRules': lb_rules } }, name=lb_name)
def configure(command_to_execute, file_uris, type_handler_version='v2.0', **_): '''Configures the resource''' os_family = ctx.node.properties.get('os_family', '').lower() if os_family == 'windows': utils.task_resource_create( VirtualMachineExtension(virtual_machine=utils.get_resource_name()), { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'properties': { 'publisher': 'Microsoft.Compute', 'type': 'CustomScriptExtension', 'typeHandlerVersion': type_handler_version, 'settings': { 'fileUris': file_uris, 'commandToExecute': command_to_execute } } }) # Write the IP address to runtime properties for the agent # Get a reference to the NIC rel_nic = utils.get_relationship_by_type(ctx.instance.relationships, constants.REL_CONNECTED_TO_NIC) # No NIC? Exit and hope the user doesn't plan to install an agent if not rel_nic: return # Get the NIC data from the API directly (because of IPConfiguration) nic = NetworkInterfaceCard(_ctx=rel_nic.target) nic_data = nic.get(utils.get_resource_name(rel_nic.target)) # Iterate over each IPConfiguration entry for ip_cfg in nic_data.get('properties', dict()).get('ipConfigurations', list()): # Get the Private IP Address endpoint ctx.instance.runtime_properties['ip'] = \ ip_cfg.get('properties', dict()).get('privateIPAddress') # Get the Public IP Address endpoint pubip_id = ip_cfg.get('properties', dict()).get('publicIPAddress', dict()).get('id') if isinstance(pubip_id, basestring): # use the ID to get the data on the public ip pubip = PublicIPAddress(_ctx=rel_nic.target) pubip.endpoint = '{0}{1}'.format(constants.CONN_API_ENDPOINT, pubip_id) pubip_data = pubip.get() if isinstance(pubip_data, dict): ctx.instance.runtime_properties['public_ip'] = \ pubip_data.get('properties', dict()).get('ipAddress') # 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_rule(**_): '''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 NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Generate a name if it doesn't exist utils.generate_resource_name(LoadBalancerRule( api_version=ctx.node.properties.get('api_version', constants.API_VER_NETWORK))) # Get the resource config res_cfg = utils.get_resource_config() # 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) lb_iface = LoadBalancer(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) lb_data = lb_iface.get(lb_name) # Get the Load Balancer Backend Pool lb_be_pool_id = utils.get_rel_id_reference( BackendAddressPool, constants.REL_CONNECTED_TO_LB_BE_POOL) # Get the Load Balancer Probe lb_probe_id = utils.get_rel_id_reference( Probe, constants.REL_CONNECTED_TO_LB_PROBE) # Get the Load Balancer Frontend IP Configuration lb_fe_ipc_name = utils.get_rel_node_name(constants.REL_CONNECTED_TO_IPC) lb_fe_ipc_id = utils.get_full_resource_id( FrontendIPConfiguration(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK) ), lb_fe_ipc_name) # Get the existing Load Balancer Rules lb_rules = lb_data.get('properties', dict()).get( 'loadBalancingRules', list()) # Update the resource config res_cfg['backendAddressPool'] = lb_be_pool_id res_cfg['frontendIPConfiguration'] = lb_fe_ipc_id res_cfg['probe'] = lb_probe_id lb_rules.append({ 'name': utils.get_resource_name(), 'properties': res_cfg }) # Update the Load Balancer with the new rule utils.task_resource_update( lb_iface, { 'properties': { 'loadBalancingRules': lb_rules } }, name=lb_name)
def create_rule(**_): '''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 NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Generate a name if it doesn't exist utils.generate_resource_name(LoadBalancerRule()) # Get the resource config res_cfg = utils.get_resource_config() # 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) lb_iface = LoadBalancer() lb_data = lb_iface.get(lb_name) # Get the Load Balancer Backend Pool lb_be_pool_id = utils.get_rel_id_reference( BackendAddressPool, constants.REL_CONNECTED_TO_LB_BE_POOL) # Get the Load Balancer Probe lb_probe_id = utils.get_rel_id_reference( Probe, constants.REL_CONNECTED_TO_LB_PROBE) # Get the Load Balancer Frontend IP Configuration lb_fe_ipc_name = utils.get_rel_node_name(constants.REL_CONNECTED_TO_IPC) lb_fe_ipc_id = utils.get_full_resource_id( FrontendIPConfiguration(), lb_fe_ipc_name) # Get the existing Load Balancer Rules lb_rules = lb_data.get('properties', dict()).get( 'loadBalancingRules', list()) # Update the resource config res_cfg['backendAddressPool'] = lb_be_pool_id res_cfg['frontendIPConfiguration'] = lb_fe_ipc_id res_cfg['probe'] = lb_probe_id lb_rules.append({ 'name': utils.get_resource_name(), 'properties': res_cfg }) # Update the Load Balancer with the new rule utils.task_resource_update( lb_iface, { 'properties': { 'loadBalancingRules': lb_rules } }, name=lb_name)
def list_keys(self, name=None): ''' Calls /listKeys :param string name: Name of the existing resource :returns: Response data from the Azure API call :rtype: dict :raises: :exc:`cloudify.exceptions.RecoverableError` ''' # Get the resource name name = name or utils.get_resource_name(self.ctx) url = '{0}/{1}/listKeys'.format(self.endpoint, name) res = self.client.request( method='post', url=url) if res.status_code != httplib.OK: raise RecoverableError( 'Unexpected status returned after calling ' '/listKeys. Status={0}'.format(res.status_code)) keys = res.json() ret = list() for key in keys: ret.append({ 'name': key, 'key': keys[key] }) return ret
def attach_ip_configuration(**_): '''Generates a usable UUID for the NIC's IP Configuration''' # Generate the IPConfiguration's name utils.generate_resource_name(FrontendIPConfiguration( load_balancer_name=utils.get_resource_name(_ctx=ctx.source), _ctx=ctx.target), _ctx=ctx.target)
def get_resource_group_name_deployment_name_and_api_version(ctx): deployment_name = utils.get_resource_name(ctx) resource_group_name = ctx.node.properties.get('resource_group_name', deployment_name) api_version = \ ctx.node.properties.get('api_version', constants.API_VER_RESOURCES) return deployment_name, resource_group_name, api_version
def create_probe(ctx, **_): """Uses an existing, or creates a new, Load Balancer Probe""" # 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) probe_name = ctx.node.properties.get('name') probe_name = \ get_unique_lb_prop_name(load_balancer, resource_group_name, load_balancer_name, "probes", probe_name) ctx.instance.runtime_properties['name'] = probe_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) # Get the existing probes lb_data = load_balancer.get(resource_group_name, lb_name) lb_probes = lb_data.get('probes', list()) lb_probes.append({ 'name': probe_name, }) lb_probes = \ utils.handle_resource_config_params(lb_probes, ctx.node.properties.get( 'resource_config', {})) # Update the Load Balancer with the new probe lb_params = { 'probes': lb_probes } # 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("probes"): if item.get("name") == probe_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 probe '{0}' " "failed with this error : {1}".format(probe_name, cr.message) )
def build_osdisk_profile(usr_osdisk=None): ''' Creates a storageProfile::osDisk object for use when creating a Virtual Machine :param dict usr_osdisk: User-override data :returns: storageProfile::osDisk object :rtype: dict ''' osdisk = dict() if isinstance(usr_osdisk, dict): osdisk = deepcopy(usr_osdisk) # Generate disk name if one wasn't provided osdisk['name'] = osdisk.get('name') or utils.get_resource_name() # If no disk URI was specified, generate one if not osdisk.get('vhd', dict()).get('uri'): osdisk['vhd'] = { 'uri': 'http://{0}.{1}/vhds/{2}.vhd'.format( utils.get_rel_node_name(constants.REL_CONNECTED_TO_SA), 'blob.core.windows.net', osdisk.get('name')) } # Fill in the blanks if the user didn't specify osdisk['caching'] = osdisk.get('caching', 'ReadWrite') osdisk['createOption'] = osdisk.get('createOption', 'FromImage') return osdisk
def attach_ip_configuration(**_): '''Generates a usable UUID for the NIC's IP Configuration''' # Generate the IPConfiguration's name utils.generate_resource_name(IPConfiguration( network_interface_card=utils.get_resource_name(_ctx=ctx.source), _ctx=ctx.target ), _ctx=ctx.target)
def detach_nic_from_backend_pool(**_): ''' Detaches a Network Interface Card's IPConfigurations from a Load Balancer Backend Pool ''' # Get the ID of the Backend Pool be_pool_id = utils.get_full_id_reference( BackendAddressPool, _ctx=ctx.target) # Get an interface to the Network Interface Card nic_iface = NetworkInterfaceCard(_ctx=ctx.source) # Get the existing NIC IPConfigurations nic_data = nic_iface.get(utils.get_resource_name(ctx.source)) nic_ip_cfgs = nic_data.get('properties', dict()).get( 'ipConfigurations', list()) # Remove the Backend Pool from the NIC IPConfigurations for ip_idx, _ in enumerate(nic_ip_cfgs): nic_pools = nic_ip_cfgs[ip_idx].get( 'properties', dict()).get( LB_ADDRPOOLS_KEY, list()) for pool_idx, nic_pool in enumerate(nic_pools): if nic_pool != be_pool_id: continue del nic_pools[pool_idx] nic_ip_cfgs[ip_idx]['properties'][LB_ADDRPOOLS_KEY] = nic_pools # Update the NIC IPConfigurations utils.task_resource_update( nic_iface, { 'properties': { 'ipConfigurations': nic_ip_cfgs } }, _ctx=ctx.source)
def build_ip_configuration(ipc): ''' Attempts to construct a proper IP Configuration from a context object :params `cloudify.context.RelationshipSubjectContext` ipc: IP Configuration context object :returns: IP Configuration dict :rtype: dict or None ''' if not ipc or not ipc.instance.relationships: return None # Find a referenced Subnet subnet = utils.get_rel_id_reference(Subnet, constants.REL_IPC_CONNECTED_TO_SUBNET, _ctx=ipc) # Find a referenced Public IP pubip = utils.get_rel_id_reference(PublicIPAddress, constants.REL_IPC_CONNECTED_TO_PUBIP, _ctx=ipc) # Build a partial config and update it with properties config return utils.dict_update( { 'name': utils.get_resource_name(ipc), 'properties': { 'subnet': subnet, 'publicIPAddress': pubip } }, utils.get_resource_config(_ctx=ipc))
def build_datadisks_profile(usr_datadisks): ''' Creates a list of storageProfile::dataDisk objects for use when creating a Virtual Machine :param dict usr_datadisks: User data :returns: List of storageProfile::dataDisk objects :rtype: list ''' datadisks = list() if not usr_datadisks: return list() for idx, usr_datadisk in enumerate(usr_datadisks): datadisk = deepcopy(usr_datadisk) # Generate disk name if one wasn't provided datadisk['name'] = datadisk.get('name') or \ '{0}-{1}'.format(utils.get_resource_name(), idx) # If no disk URI was specified, generate one if not datadisk.get('vhd', dict()).get('uri'): datadisk['vhd'] = { 'uri': 'http://{0}.{1}/vhds/{2}.vhd'.format( utils.get_rel_node_name(constants.REL_CONNECTED_TO_SA), 'blob.' + ctx.node.properties['storage_endpoint'], datadisk.get('name')) } # Fill in the blanks if the user didn't specify datadisk['lun'] = datadisk.get('lun', idx) datadisk['createOption'] = datadisk.get('createOption', 'Empty') datadisks.append(datadisk) return datadisks
def detach_nic_from_backend_pool(**_): ''' Detaches a Network Interface Card's IPConfigurations from a Load Balancer Backend Pool ''' # Get the ID of the Backend Pool be_pool_id = utils.get_full_id_reference(BackendAddressPool, _ctx=ctx.target) # Get an interface to the Network Interface Card nic_iface = NetworkInterfaceCard(_ctx=ctx.source) # Get the existing NIC IPConfigurations nic_data = nic_iface.get(utils.get_resource_name(ctx.source)) nic_ip_cfgs = nic_data.get('properties', dict()).get('ipConfigurations', list()) # Remove the Backend Pool from the NIC IPConfigurations for ip_idx, _ in enumerate(nic_ip_cfgs): nic_pools = nic_ip_cfgs[ip_idx].get('properties', dict()).get( LB_ADDRPOOLS_KEY, list()) for pool_idx, nic_pool in enumerate(nic_pools): if nic_pool != be_pool_id: continue del nic_pools[pool_idx] nic_ip_cfgs[ip_idx]['properties'][LB_ADDRPOOLS_KEY] = nic_pools # Update the NIC IPConfigurations utils.task_resource_update( nic_iface, {'properties': { 'ipConfigurations': nic_ip_cfgs }}, _ctx=ctx.source)
def attach_ip_configuration(**_): '''Generates a usable UUID for the NIC's IP Configuration''' # Generate the IPConfiguration's name utils.generate_resource_name(FrontendIPConfiguration( load_balancer_name=utils.get_resource_name(_ctx=ctx.source), _ctx=ctx.target ), _ctx=ctx.target)
def build_ip_configuration(ipc): ''' Attempts to construct a proper IP Configuration from a context object :params `cloudify.context.RelationshipSubjectContext` ipc: IP Configuration context object :returns: IP Configuration dict :rtype: dict or None ''' if not ipc or not ipc.instance.relationships: return None # Find a referenced Subnet subnet = utils.get_rel_id_reference( Subnet, constants.REL_IPC_CONNECTED_TO_SUBNET, _ctx=ipc) # Find a referenced Public IP pubip = utils.get_rel_id_reference( PublicIPAddress, constants.REL_IPC_CONNECTED_TO_PUBIP, _ctx=ipc) ip_configuration = { 'name': utils.get_resource_name(ipc), 'properties': { 'subnet': subnet, 'publicIPAddress': pubip } } ip_configuration['properties'] = utils.dict_update( ip_configuration['properties'], utils.get_resource_config(_ctx=ipc)) return ip_configuration
def build_osdisk_profile(usr_osdisk=None): ''' Creates a storageProfile::osDisk object for use when creating a Virtual Machine :param dict usr_osdisk: User-override data :returns: storageProfile::osDisk object :rtype: dict ''' osdisk = dict() if isinstance(usr_osdisk, dict): osdisk = deepcopy(usr_osdisk) # Generate disk name if one wasn't provided osdisk['name'] = osdisk.get('name') or utils.get_resource_name() # If no disk URI was specified, generate one # Unless this is a managedDisk. if not osdisk.get('vhd', dict()).get('uri') and \ 'managedDisk' not in osdisk: osdisk['vhd'] = { 'uri': 'http://{0}.{1}/vhds/{2}.vhd'.format( utils.get_rel_node_name(constants.REL_CONNECTED_TO_SA), 'blob.' + ctx.node.properties['storage_endpoint'], osdisk.get('name')) } # Fill in the blanks if the user didn't specify osdisk['caching'] = osdisk.get('caching', 'ReadWrite') osdisk['createOption'] = osdisk.get('createOption', 'FromImage') return osdisk
def detach_data_disk(**_): '''Detaches a data disk''' vm_iface = VirtualMachine(_ctx=ctx.source, api_version=ctx.source.node.properties.get( 'api_version', constants.API_VER_COMPUTE)) vm_state = vm_iface.get(name=utils.get_resource_name(_ctx=ctx.source)) data_disks = [ x for x in vm_state.get('properties', dict()).get( 'storageProfile', dict()).get('dataDisks', list()) if x.get('vhd', dict()).get('uri') != ctx.target.instance.runtime_properties['uri'] ] ctx.logger.info('async_op: {0}'.format( ctx.source.instance.runtime_properties.get('async_op'))) # Update the VM utils.task_resource_update( VirtualMachine(_ctx=ctx.source, api_version=ctx.source.node.properties.get( 'api_version', constants.API_VER_COMPUTE)), { 'location': ctx.source.node.properties.get('location'), 'properties': { 'storageProfile': { 'dataDisks': data_disks } } }, force=True, _ctx=ctx.source)
def build_datadisks_profile(usr_datadisks): ''' Creates a list of storageProfile::dataDisk objects for use when creating a Virtual Machine :param dict usr_datadisks: User data :returns: List of storageProfile::dataDisk objects :rtype: list ''' datadisks = list() if not usr_datadisks: return list() for idx, usr_datadisk in enumerate(usr_datadisks): datadisk = deepcopy(usr_datadisk) # Generate disk name if one wasn't provided datadisk['name'] = datadisk.get('name') or \ '{0}-{1}'.format(utils.get_resource_name(), idx) # If no disk URI was specified, generate one if not datadisk.get('vhd', dict()).get('uri'): datadisk['vhd'] = { 'uri': 'http://{0}.{1}/vhds/{2}.vhd'.format( utils.get_rel_node_name(constants.REL_CONNECTED_TO_SA), 'blob.core.windows.net', datadisk.get('name')) } # Fill in the blanks if the user didn't specify datadisk['lun'] = datadisk.get('lun', idx) datadisk['createOption'] = datadisk.get('createOption', 'Empty') datadisks.append(datadisk) return datadisks
def detach_data_disk(**_): '''Detaches a data disk''' vm_iface = VirtualMachine(_ctx=ctx.source) vm_state = vm_iface.get(name=utils.get_resource_name(_ctx=ctx.source)) data_disks = [ x for x in vm_state.get( 'properties', dict()).get( 'storageProfile', dict()).get( 'dataDisks', list()) if x.get('vhd', dict()).get('uri') != ctx.target.instance.runtime_properties['uri'] ] ctx.logger.info('async_op: {0}'.format( ctx.source.instance.runtime_properties.get('async_op'))) # Update the VM utils.task_resource_update( VirtualMachine(_ctx=ctx.source), { 'location': ctx.source.node.properties.get('location'), 'properties': { 'storageProfile': { 'dataDisks': data_disks } } }, force=True, _ctx=ctx.source )
def delete(ctx, **_): """Deletes a Resource Group""" if ctx.node.properties.get('use_external_resource', False): return 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) api_version = \ ctx.node.properties.get('api_version', constants.API_VER_RESOURCES) resource_group = ResourceGroup(azure_config, ctx.logger, api_version) try: resource_group.get(name) except CloudError: ctx.logger.info("Resource with name {0} doesn't exist".format(name)) return try: resource_group.delete(name) utils.runtime_properties_cleanup(ctx) except CloudError as cr: raise cfy_exc.NonRecoverableError( "delete resource_group '{0}' " "failed with this error : {1}".format(name, cr.message))
def create(ctx, **_): """Uses an existing, or creates a new, Resource Group""" 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_params = { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags') } api_version = \ ctx.node.properties.get('api_version', constants.API_VER_RESOURCES) resource_group = ResourceGroup(azure_config, ctx.logger, api_version) try: result = \ resource_group.create_or_update( name, resource_group_params) except CloudError as cr: raise cfy_exc.NonRecoverableError( "create resource_group '{0}' " "failed with this error : {1}".format(name, cr.message)) ctx.instance.runtime_properties['resource'] = result ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
def attach_ip_configuration(**_): '''Generates a usable UUID for the NIC's IP Configuration''' # Generate the IPConfiguration's name utils.generate_resource_name(IPConfiguration( network_interface_card=utils.get_resource_name(_ctx=ctx.source), _ctx=ctx.target), _ctx=ctx.target)
def create(ctx, **_): """Uses an existing, or creates a new, Load Balancer""" name = utils.get_resource_name(ctx) resource_group_name = utils.get_resource_group(ctx) ctx.logger.info("Created Load Balancer with name {0} " "inside ResourceGroup {1}".format(name, resource_group_name)) ctx.instance.runtime_properties['resource_group'] = resource_group_name
def attach_data_disk(lun, **_): '''Attaches a data disk''' vm_iface = VirtualMachine(_ctx=ctx.source, api_version=ctx.source.node.properties.get( 'api_version', constants.API_VER_COMPUTE)) vm_state = vm_iface.get(name=utils.get_resource_name(_ctx=ctx.source)) data_disks = vm_state.get('properties', dict()).get('storageProfile', dict()).get('dataDisks', list()) # Get the createOption create_opt = 'Empty' if ctx.target.node.properties.get('use_external_resource', False): create_opt = 'Attach' # Add the disk to the list data_disks.append({ 'name': utils.get_resource_name(_ctx=ctx.target), 'lun': lun, 'diskSizeGB': ctx.target.instance.runtime_properties['diskSizeGB'], 'vhd': { 'uri': ctx.target.instance.runtime_properties['uri'] }, 'createOption': create_opt, 'caching': 'None' }) ctx.logger.info('async_op: {0}'.format( ctx.source.instance.runtime_properties.get('async_op'))) # Update the VM utils.task_resource_update( VirtualMachine(_ctx=ctx.source, api_version=ctx.source.node.properties.get( 'api_version', constants.API_VER_COMPUTE)), { 'location': ctx.source.node.properties.get('location'), 'properties': { 'storageProfile': { 'dataDisks': data_disks } } }, force=True, _ctx=ctx.source)
def configure(**_): '''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 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('properties', dict()).get('publicIPAddress'): if ip_cfg.get('properties', dict()).get('subnet'): del ip_cfg['properties']['subnet'] # Create a resource (if necessary) utils.task_resource_create( LoadBalancer(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)), { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'properties': utils.dict_update(utils.get_resource_config(), {'frontendIPConfigurations': fe_ip_cfg}) }) # Get an interface to the Load Balancer lb_iface = LoadBalancer(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) lb_data = lb_iface.get(utils.get_resource_name()) # Get the ID of the Frontend IP Configuration for fe_ipc_data in lb_data.get('properties', dict()).get('frontendIPConfigurations', list()): ipc_iface = IPConfiguration() ipc_id = fe_ipc_data.get('id') if not ipc_id: break ipc_iface.endpoint = '{0}{1}'.format(constants.CONN_API_ENDPOINT, ipc_id) # Get the Frontend private IP address ipc_data = ipc_iface.get() ctx.instance.runtime_properties['ip'] = \ ipc_data.get('properties', dict()).get('privateIPAddress') # Get the ID of the Frontend Public IP Configuration pipc_iface = PublicIPAddress() pipc_id = fe_ipc_data.get('properties', dict()).get('publicIPAddress', dict()).get('id') if not pipc_id: break pipc_iface.endpoint = '{0}{1}'.format(constants.CONN_API_ENDPOINT, pipc_id) # Get the Frontend public IP address pipc_data = pipc_iface.get() ctx.instance.runtime_properties['public_ip'] = \ pipc_data.get('properties', dict()).get('ipAddress')
def start(**_): ''' Stores NIC IPs in runtime properties. ''' creds = utils.get_credentials(_ctx=ctx) nic_iface = NetworkInterfaceCard( _ctx=ctx, api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) nic_name = utils.get_resource_name(ctx) nic_data = nic_iface.get(nic_name) for ip_cfg in nic_data.get( 'properties', dict()).get( 'ipConfigurations', list()): # Get the Private IP Address endpoint ctx.instance.runtime_properties['ip'] = \ ip_cfg.get('properties', dict()).get('privateIPAddress') # Get the Public IP Address endpoint pubip_id = ip_cfg.get( 'properties', dict()).get( 'publicIPAddress', dict()).get('id') if isinstance(pubip_id, basestring): # use the ID to get the data on the public ip pubip = PublicIPAddress( _ctx=ctx, api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) pubip.endpoint = '{0}{1}'.format( creds.endpoints_resource_manager, pubip_id) pubip_data = pubip.get() if isinstance(pubip_data, dict): public_ip = \ pubip_data.get('properties', dict()).get('ipAddress') # Maintained for backwards compatibility. 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. public_ip_addresses = \ ctx.instance.runtime_properties.get( PUBLIC_IP_PROPERTY, []) if public_ip not in public_ip_addresses: public_ip_addresses.append(public_ip) ctx.instance.runtime_properties['public_ip_addresses'] = \ public_ip_addresses
def configure(**_): '''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 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('properties', dict()).get('publicIPAddress'): if ip_cfg.get('properties', dict()).get('subnet'): del ip_cfg['properties']['subnet'] # Create a resource (if necessary) utils.task_resource_create( LoadBalancer(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)), { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'properties': utils.dict_update( utils.get_resource_config(), { 'frontendIPConfigurations': fe_ip_cfg }) }) # Get an interface to the Load Balancer lb_iface = LoadBalancer(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) lb_data = lb_iface.get(utils.get_resource_name()) # Get the ID of the Frontend IP Configuration for fe_ipc_data in lb_data.get('properties', dict()).get( 'frontendIPConfigurations', list()): ipc_iface = IPConfiguration() ipc_id = fe_ipc_data.get('id') if not ipc_id: break ipc_iface.endpoint = '{0}{1}'.format( constants.CONN_API_ENDPOINT, ipc_id) # Get the Frontend private IP address ipc_data = ipc_iface.get() ctx.instance.runtime_properties['ip'] = \ ipc_data.get('properties', dict()).get('privateIPAddress') # Get the ID of the Frontend Public IP Configuration pipc_iface = PublicIPAddress() pipc_id = fe_ipc_data.get('properties', dict()).get( 'publicIPAddress', dict()).get('id') if not pipc_id: break pipc_iface.endpoint = '{0}{1}'.format( constants.CONN_API_ENDPOINT, pipc_id) # Get the Frontend public IP address pipc_data = pipc_iface.get() ctx.instance.runtime_properties['public_ip'] = \ pipc_data.get('properties', dict()).get('ipAddress')
def attach_data_disk(lun, **_): '''Attaches a data disk''' vm_iface = VirtualMachine(_ctx=ctx.source, api_version=ctx.source.node.properties.get( 'api_version', constants.API_VER_COMPUTE)) vm_state = vm_iface.get(name=utils.get_resource_name(_ctx=ctx.source)) data_disks = vm_state.get( 'properties', dict()).get( 'storageProfile', dict()).get( 'dataDisks', list()) # Get the createOption create_opt = 'Empty' if ctx.target.node.properties.get('use_external_resource', False): create_opt = 'Attach' # Add the disk to the list data_disks.append({ 'name': utils.get_resource_name(_ctx=ctx.target), 'lun': lun, 'diskSizeGB': ctx.target.instance.runtime_properties['diskSizeGB'], 'vhd': { 'uri': ctx.target.instance.runtime_properties['uri'] }, 'createOption': create_opt, 'caching': 'None' }) ctx.logger.info('async_op: {0}'.format( ctx.source.instance.runtime_properties.get('async_op'))) # Update the VM utils.task_resource_update( VirtualMachine(_ctx=ctx.source, api_version=ctx.source.node.properties.get( 'api_version', constants.API_VER_COMPUTE)), { 'location': ctx.source.node.properties.get('location'), 'properties': { 'storageProfile': { 'dataDisks': data_disks } } }, force=True, _ctx=ctx.source )
def create_incoming_nat_rule(**_): '''Uses an existing, or creates a new, Load Balancer Incoming NAT Rule''' # Check if invalid external resource if ctx.node.properties.get('use_external_resource', False) and \ not ctx.node.properties.get('name'): raise NonRecoverableError( '"use_external_resource" specified without a resource "name"') # Generate a name if it doesn't exist utils.generate_resource_name(InboundNATRule()) # 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) lb_iface = LoadBalancer() # Get the resource config res_cfg = utils.get_resource_config() # Get the existing rules lb_data = lb_iface.get(lb_name) lb_rules = lb_data.get('properties', dict()).get( 'inboundNatRules', list()) # Get the Load Balancer Frontend IP Configuration lb_fe_ipc_name = utils.get_rel_node_name(constants.REL_CONNECTED_TO_IPC) lb_fe_ipc_id = utils.get_full_resource_id( FrontendIPConfiguration(), lb_fe_ipc_name) # Update the resource config res_cfg['frontendIPConfiguration'] = lb_fe_ipc_id lb_rules.append({ 'name': utils.get_resource_name(), 'properties': res_cfg }) # Update the Load Balancer with the new NAT rule utils.task_resource_update( lb_iface, { 'properties': { 'inboundNatRules': lb_rules } }, name=lb_name)
def create(ctx, **_): """Uses an existing, or creates a new, Storage Account""" # Generate a resource name (if needed) 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.info("azure_config id deprecated please use client_config") 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_STORAGE) storage_account = StorageAccount(azure_config, ctx.logger, api_version) sa_sku = ctx.node.properties.get('sku') sa_params = { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'account_type': ctx.node.properties.get('resource_config', {}).get('accountType'), 'network_rule_set': ctx.node.properties.get('resource_config', {}).get('networkAcls'), 'enable_https_traffic_only': ctx.node.properties.get('resource_config', {}).get('supportsHttpsTrafficOnly'), 'encryption': { 'services': ctx.node.properties.get('resource_config', {}).get('encryption'), 'key_source': ctx.node.properties.get('resource_config', {}).get('keySource'), } } if sa_sku: sa_params['sku'] = sa_sku # clean empty values from params sa_params = \ utils.cleanup_empty_params(sa_params) try: result = \ storage_account.create( resource_group_name, name, sa_params) except CloudError as cr: raise cfy_exc.NonRecoverableError( "create storage_account '{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 start(**_): ''' Stores NIC IPs in runtime properties. ''' creds = utils.get_credentials(_ctx=ctx) nic_iface = NetworkInterfaceCard(_ctx=ctx, api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) nic_name = utils.get_resource_name(ctx) nic_data = nic_iface.get(nic_name) for ip_cfg in nic_data.get('properties', dict()).get('ipConfigurations', list()): # Get the Private IP Address endpoint ctx.instance.runtime_properties['ip'] = \ ip_cfg.get('properties', dict()).get('privateIPAddress') # Get the Public IP Address endpoint pubip_id = ip_cfg.get('properties', dict()).get('publicIPAddress', dict()).get('id') if isinstance(pubip_id, basestring): # use the ID to get the data on the public ip pubip = PublicIPAddress(_ctx=ctx, api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) pubip.endpoint = '{0}{1}'.format(creds.endpoints_resource_manager, pubip_id) pubip_data = pubip.get() if isinstance(pubip_data, dict): public_ip = \ pubip_data.get('properties', dict()).get('ipAddress') # Maintained for backwards compatibility. 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. public_ip_addresses = \ ctx.instance.runtime_properties.get( PUBLIC_IP_PROPERTY, []) if public_ip not in public_ip_addresses: public_ip_addresses.append(public_ip) ctx.instance.runtime_properties['public_ip_addresses'] = \ public_ip_addresses
def delete_probe(**_): '''Deletes a Load Balancer Probe''' if ctx.node.properties.get('use_external_resource', False): return # 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) lb_iface = LoadBalancer(_ctx=lb_rel.target, api_version=ctx.node.properties.get( 'api_version', constants.API_VER_NETWORK)) # Get the existing probes lb_data = lb_iface.get(lb_name) lb_probes = lb_data.get('properties', dict()).get('probes', list()) for idx, probe in enumerate(lb_probes): if probe.get('name') == utils.get_resource_name(): del lb_probes[idx] # Update the Load Balancer with the new probes list utils.task_resource_update(lb_iface, {'properties': { 'probes': lb_probes }}, name=lb_name)
def get_connected_nsg(): '''Finds a connected Network Security Group''' nsg = None nsg_name = None for rel in ctx.instance.relationships: if constants.REL_NIC_CONNECTED_TO_NSG in rel.type_hierarchy: nsg = NetworkSecurityGroup(_ctx=rel.target) nsg_name = utils.get_resource_name(rel.target) return { 'id': '/subscriptions/{0}{1}/{2}'.format( utils.get_subscription_id(_ctx=nsg.ctx), nsg.endpoint, nsg_name) } if nsg else None
def build_ip_configuration(ipc): """ Attempts to construct a proper IP Configuration from a context object :params `cloudify.context.RelationshipSubjectContext` ipc: IP Configuration context object :returns: IP Configuration dict :rtype: dict or None """ if not ipc or not ipc.instance.relationships: return None # Find a referenced Subnet/PublicIPAddress rel_sub_type = constants.REL_IPC_CONNECTED_TO_SUBNET rel_pip_type = constants.REL_IPC_CONNECTED_TO_PUBIP subnet = None pubip = None for rel in ipc.instance.relationships: if isinstance(rel_sub_type, tuple): if any(x in rel.type_hierarchy for x in rel_sub_type): subnet = { 'id': rel.target.instance.runtime_properties['resource_id'] } else: if rel_sub_type in rel.type_hierarchy: subnet = { 'id': rel.target.instance.runtime_properties['resource_id'] } if isinstance(rel_pip_type, tuple): if any(x in rel.type_hierarchy for x in rel_pip_type): pubip = { 'id': rel.target.instance.runtime_properties['resource_id'] } else: if rel_pip_type in rel.type_hierarchy: pubip = { 'id': rel.target.instance.runtime_properties['resource_id'] } ip_configuration = { 'name': utils.get_resource_name(ipc), 'subnet': subnet, 'public_ip_address': pubip } ip_configuration = \ utils.handle_resource_config_params(ip_configuration, ipc.node.properties.get( "resource_config", {})) return ip_configuration
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) storage_account_name = utils.get_resource_name(_ctx=storage_account) # Get the storage account keys keys = StorageAccount(_ctx=storage_account).list_keys() if not isinstance(keys, list) or len(keys) < 1: raise RecoverableError( 'StorageAccount reported no usable authentication keys') # Get an interface to the Storage Account storage_account_key = keys[0].get('key') return CloudStorageAccount(account_name=storage_account_name, account_key=storage_account_key)
def attach_route_table(**_): '''Attaches a Route Table (source) to the Subnet (target)''' rtbl = RouteTable(_ctx=ctx.source) rtbl_name = utils.get_resource_name(ctx.source) # Attach utils.task_resource_update( Subnet(_ctx=ctx.target), { 'properties': { 'routeTable': { 'id': '/subscriptions/{0}{1}/{2}'.format( utils.get_subscription_id(_ctx=ctx.source), rtbl.endpoint, rtbl_name) } } }, _ctx=ctx.target)
def attach_network_security_group(**_): '''Attaches a Network Security Group (source) to the Subnet (target)''' nsg = NetworkSecurityGroup(_ctx=ctx.source) nsg_name = utils.get_resource_name(ctx.source) # Attach utils.task_resource_update(Subnet(_ctx=ctx.target), { 'properties': { 'networkSecurityGroup': { 'id': '/subscriptions/{0}{1}/{2}'.format( utils.get_subscription_id(_ctx=ctx.source), nsg.endpoint, nsg_name) } } }, _ctx=ctx.target)
def attach_network_security_group(**_): '''Attaches a Network Security Group (source) to the Subnet (target)''' nsg = NetworkSecurityGroup(_ctx=ctx.source) nsg_name = utils.get_resource_name(ctx.source) # Attach utils.task_resource_update( Subnet(_ctx=ctx.target), { 'properties': { 'networkSecurityGroup': { 'id': '/subscriptions/{0}{1}/{2}'.format( utils.get_subscription_id(_ctx=ctx.source), nsg.endpoint, nsg_name) } } }, _ctx=ctx.target)
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) storage_account_name = utils.get_resource_name(_ctx=storage_account) # Get the storage account keys keys = StorageAccount(_ctx=storage_account).list_keys() if not isinstance(keys, list) or len(keys) < 1: raise RecoverableError( 'StorageAccount reported no usable authentication keys') # Get an interface to the Storage Account storage_account_key = keys[0].get('key') return CloudStorageAccount( account_name=storage_account_name, account_key=storage_account_key)
def configure(command_to_execute, file_uris, **_): '''Configures the resource''' os_family = ctx.node.properties.get('os_family', '').lower() if os_family == 'windows': # By default, this should enable WinRM HTTP (unencrypted) # This entire function can be overridden from the plugin utils.task_resource_create( VirtualMachineExtension( virtual_machine=utils.get_resource_name() ), { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'properties': { 'publisher': 'Microsoft.Compute', 'type': 'CustomScriptExtension', 'typeHandlerVersion': '1.4', 'settings': { 'fileUris': file_uris, 'commandToExecute': command_to_execute } } }) # Write the IP address to runtime properties for the agent # Get a reference to the NIC rel_nic = utils.get_relationship_by_type( ctx.instance.relationships, constants.REL_CONNECTED_TO_NIC) # No NIC? Exit and hope the user doesn't plan to install an agent if not rel_nic: return # Get the NIC data from the API directly (because of IPConfiguration) nic = NetworkInterfaceCard(_ctx=rel_nic.target) nic_data = nic.get(utils.get_resource_name(rel_nic.target)) # Iterate over each IPConfiguration entry for ip_cfg in nic_data.get( 'properties', dict()).get( 'ipConfigurations', list()): # Get the Private IP Address endpoint ctx.instance.runtime_properties['ip'] = \ ip_cfg.get('properties', dict()).get('privateIPAddress') # Get the Public IP Address endpoint pubip_id = ip_cfg.get( 'properties', dict()).get( 'publicIPAddress', dict()).get('id') if isinstance(pubip_id, basestring): # use the ID to get the data on the public ip pubip = PublicIPAddress(_ctx=rel_nic.target) pubip.endpoint = '{0}{1}'.format( constants.CONN_API_ENDPOINT, pubip_id) pubip_data = pubip.get() if isinstance(pubip_data, dict): ctx.instance.runtime_properties['public_ip'] = \ pubip_data.get('properties', dict()).get('ipAddress') # 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(**_): '''Uses an existing, or creates a new, Virtual Machine''' # Generate a resource name (if needed) utils.generate_resource_name( VirtualMachine(), generator=vm_name_generator) res_cfg = utils.get_resource_config() or dict() # Build storage profile osdisk = build_osdisk_profile( res_cfg.get('storageProfile', dict()).get('osDisk', dict())) datadisks = build_datadisks_profile( res_cfg.get('storageProfile', dict()).get('dataDisks', list())) storage_profile = { 'osDisk': osdisk, 'dataDisks': datadisks } # Build the network profile network_profile = build_network_profile() # 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 = { 'windowsConfiguration': { # This is required for extension scripts to work 'provisionVMAgent': True, 'winRM': { 'listeners': [{ 'protocol': 'Http', 'certificateUrl': None }] } }, 'linuxConfiguration': None } elif not res_cfg.get('osProfile', dict()).get('linuxConfiguration'): os_profile = { 'linuxConfiguration': { 'disablePasswordAuthentication': False }, 'windowsConfiguration': None } # Set the computerName if it's not set already os_profile['computerName'] = \ res_cfg.get( 'osProfile', dict() ).get('computerName', utils.get_resource_name()) # Create a resource (if necessary) utils.task_resource_create( VirtualMachine(), { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'plan': ctx.node.properties.get('plan'), 'properties': utils.dict_update( utils.get_resource_config(), { 'availabilitySet': utils.get_rel_id_reference( AvailabilitySet, constants.REL_CONNECTED_TO_AS), 'networkProfile': network_profile, 'storageProfile': storage_profile, 'osProfile': os_profile } ) })
def create_file_share(**_): '''Creates an Azure File Share''' # Get resource config values res_cfg = utils.get_resource_config() or dict() share_name = ctx.node.properties.get('name') 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) storage_account_name = utils.get_resource_name(_ctx=storage_account) # Get the storage account keys keys = StorageAccount(_ctx=storage_account).list_keys() if not isinstance(keys, list) or len(keys) < 1: raise RecoverableError( 'StorageAccount reported no usable authentication keys') # Get an interface to the Storage Account storage_account_key = keys[0].get('key') 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 xrange(0, 10): tmpname = file_share_name_generator() if not file_share_exists(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(command_to_execute, file_uris, type_handler_version='v2.0', **_): '''Configures the resource''' os_family = ctx.node.properties.get('os_family', '').lower() if os_family == 'windows': utils.task_resource_create( VirtualMachineExtension( virtual_machine=utils.get_resource_name(), api_version=ctx.node.properties.get('api_version', constants.API_VER_COMPUTE) ), { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'properties': { 'publisher': 'Microsoft.Compute', 'type': 'CustomScriptExtension', 'typeHandlerVersion': type_handler_version, 'settings': { 'fileUris': file_uris, 'commandToExecute': command_to_execute } } }) virtual_machine_name = ctx.instance.runtime_properties.get('name') virtual_machine_iface = \ VirtualMachine( api_version=ctx.node.properties.get( 'api_version', constants.API_VER_COMPUTE)).get( name=virtual_machine_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) # No NIC? Exit and hope the user doesn't plan to install an agent if not rel_nics: return for rel_nic in rel_nics: # Get the NIC data from the API directly (because of IPConfiguration) nic_iface = NetworkInterfaceCard( _ctx=rel_nic.target, api_version=rel_nic.target.node.properties.get( 'api_version', constants.API_VER_NETWORK)) nic_name = utils.get_resource_name(rel_nic.target) nic_data = nic_iface.get(nic_name) nic_virtual_machine_id = nic_data.get( 'properties', dict()).get( 'virtualMachine', dict()).get('id') if virtual_machine_name not in nic_virtual_machine_id: nic_data['properties'] = \ utils.dict_update( nic_data.get('properties', {}), { 'virtualMachine': { 'id': virtual_machine_iface.get('id') } } ) utils.task_resource_update( nic_iface, nic_data, _ctx=rel_nic.target) nic_data = nic_iface.get(nic_name) if virtual_machine_name not in nic_data.get( 'properties', dict()).get( 'virtualMachine', dict()).get('id', str()): return ctx.operation.retry( message='Waiting for NIC {0} to ' 'attach to VM {1}..' .format(nic_name, virtual_machine_name), retry_after=10) # Iterate over each IPConfiguration entry creds = utils.get_credentials(_ctx=ctx) for ip_cfg in nic_data.get( 'properties', dict()).get( 'ipConfigurations', list()): # Get the Private IP Address endpoint ctx.instance.runtime_properties['ip'] = \ ip_cfg.get('properties', dict()).get('privateIPAddress') # Get the Public IP Address endpoint pubip_id = ip_cfg.get( 'properties', dict()).get( 'publicIPAddress', dict()).get('id') if isinstance(pubip_id, basestring): # use the ID to get the data on the public ip pubip = PublicIPAddress( _ctx=rel_nic.target, api_version=rel_nic.target.node.properties.get( 'api_version', constants.API_VER_NETWORK)) pubip.endpoint = '{0}{1}'.format( creds.endpoints_resource_manager, pubip_id) pubip_data = pubip.get() if isinstance(pubip_data, dict): public_ip = \ pubip_data.get('properties', dict()).get('ipAddress') # Maintained for backwards compatibility. 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. public_ip_addresses = \ ctx.instance.runtime_properties.get( PUBLIC_IP_PROPERTY, []) if public_ip not in public_ip_addresses: public_ip_addresses.append(public_ip) ctx.instance.runtime_properties['public_ip_addresses'] = \ public_ip_addresses # 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(args=None, **_): '''Uses an existing, or creates a new, Virtual Machine''' # Generate a resource name (if needed) utils.generate_resource_name( VirtualMachine(api_version=ctx.node.properties.get( 'api_version', constants.API_VER_COMPUTE)), generator=vm_name_generator) res_cfg = utils.get_resource_config(args=args) or dict() # Build storage profile osdisk = build_osdisk_profile( res_cfg.get('storageProfile', dict()).get('osDisk', dict())) datadisks = build_datadisks_profile( res_cfg.get('storageProfile', dict()).get('dataDisks', list())) storage_profile = { 'osDisk': osdisk, 'dataDisks': datadisks } # Build the network profile network_profile = build_network_profile() # 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 = { 'windowsConfiguration': { # This is required for extension scripts to work 'provisionVMAgent': True, 'winRM': { 'listeners': [{ 'protocol': 'Http', 'certificateUrl': None }] } }, 'linuxConfiguration': None } elif not res_cfg.get('osProfile', dict()).get('linuxConfiguration'): os_profile = { 'linuxConfiguration': { 'disablePasswordAuthentication': False }, 'windowsConfiguration': None } # Set the computerName if it's not set already os_profile['computerName'] = \ res_cfg.get( 'osProfile', dict() ).get('computerName', utils.get_resource_name()) resource_create_payload = \ { 'location': ctx.node.properties.get('location'), 'tags': ctx.node.properties.get('tags'), 'plan': ctx.node.properties.get('plan'), 'properties': utils.dict_update( utils.get_resource_config(args=args), { 'availabilitySet': utils.get_rel_id_reference( AvailabilitySet, constants.REL_CONNECTED_TO_AS), 'networkProfile': network_profile, 'storageProfile': storage_profile, 'osProfile': os_profile } ) } # support userdata from args. os_profile = resource_create_payload['properties']['osProfile'] userdata = _handle_userdata(os_profile.get('customData')) if userdata: ctx.logger.warn( 'Azure customData implementation is dependent on ' 'Virtual Machine image support.') os_profile['customData'] = base64.b64encode(userdata.encode()) # Remove customData from osProfile if empty to avoid 400 Error. elif 'customData' in resource_create_payload['properties']['osProfile']: del resource_create_payload['properties']['osProfile']['customData'] # Create a resource (if necessary) utils.task_resource_create(VirtualMachine( api_version=ctx.node.properties.get( 'api_version', constants.API_VER_COMPUTE)), resource_create_payload)