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)
Ejemplo n.º 9
0
 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)
Ejemplo n.º 10
0
 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)
Ejemplo n.º 11
0
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", "")
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
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
Ejemplo n.º 15
0
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)
            )
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
 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)
Ejemplo n.º 18
0
        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)
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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')))
Ejemplo n.º 21
0
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", "")