Example #1
0
def GenerateComputeVM(context, create_disks_separately=True):
  """Generates one VM instance resource.

  Args:
    context: Template context dictionary.
    create_disks_separately: When true (default), all new disk resources are
      created as separate resources. This is legacy behaviour from when multiple
      disks creation was not allowed in the disks property.
  Returns:
    dictionary representing instance resource.
  """
  prop = context.properties
  boot_disk_type = prop.setdefault(BOOTDISKTYPE, DEFAULT_DISKTYPE)
  prop[default.DISKTYPE] = boot_disk_type
  can_ip_fwd = prop.setdefault(CAN_IP_FWD, DEFAULT_IP_FWD)
  disks = prop.setdefault(default.DISKS, list())
  local_ssd = prop.setdefault(default.LOCAL_SSD, 0)

  if disks:
    if create_disks_separately:
      # Legacy alternative from when multiple disks on creation were not allowed
      new_disks = prop.setdefault(default.DISK_RESOURCES, list())
      SetDiskProperties(context, disks)
      disks, prop[DISK_RESOURCES] = GenerateDisks(context, disks, new_disks)
    else:
      # All new disks (except local ssd) must provide a sourceImage or existing
      # source. Add blank source image if non provided.
      SetDiskProperties(context, disks, add_blank_src_img=True)

  machine_type = prop.setdefault(MACHINETYPE, DEFAULT_MACHINETYPE)
  metadata = prop.setdefault(METADATA, dict())
  SetMetadataDefaults(metadata)
  network = prop.setdefault(NETWORK, DEFAULT_NETWORK)
  vm_name = MakeVMName(context)
  provide_boot = prop.setdefault(PROVIDE_BOOT, DEFAULT_PROVIDE_BOOT)
  tags = prop.setdefault(TAGS, dict([('items', [])]))
  zone = prop.setdefault(ZONE, DEFAULT_ZONE)
  has_external_ip = prop.get(HAS_EXTERNAL_IP, DEFAULT_HAS_EXTERNAL_IP)
  static_ip = prop.get(STATIC_IP, DEFAULT_STATIC_IP)
  nat_ip = prop.get(NAT_IP, None)

  if provide_boot:
    dev_mode = DEVIMAGE in prop and prop[DEVIMAGE]
    src_image = common.MakeC2DImageLink(prop[SRCIMAGE], dev_mode)
    boot_name = common.AutoName(context.env['name'], default.DISK, 'boot')
    disk_size = prop.get(BOOTDISKSIZE, DEFAULT_BOOTDISKSIZE)
    disk_type = common.MakeLocalComputeLink(context, DISKTYPE)
    autodelete = prop.get(AUTODELETE_BOOTDISK, DEFAULT_AUTODELETE_BOOTDISK)
    disks = PrependBootDisk(disks, boot_name, disk_type, disk_size, src_image,
                            autodelete)
  if local_ssd:
    disks = AppendLocalSSDDisks(context, disks, local_ssd)
  machine_type = common.MakeLocalComputeLink(context, default.MACHINETYPE)
  network = common.MakeGlobalComputeLink(context, default.NETWORK)
  subnetwork = ''
  if default.SUBNETWORK in prop:
    subnetwork = common.MakeSubnetworkComputeLink(context, default.SUBNETWORK)

  # To be consistent with Dev console and gcloud, service accounts need to be
  #  explicitly disabled
  remove_scopes = prop[NO_SCOPE] if NO_SCOPE in prop else False
  if remove_scopes and SERVICE_ACCOUNTS in prop:
    prop.pop(SERVICE_ACCOUNTS)
  else:  # Make sure there is a default service account
    prop.setdefault(SERVICE_ACCOUNTS, copy.deepcopy(DEFAULT_SERVICE_ACCOUNT))

  resource = []

  access_configs = []
  if has_external_ip:
    access_config = {'name': default.EXTERNAL, 'type': default.ONE_NAT}
    access_configs.append(access_config)
    if static_ip and nat_ip:
      raise common.Error(
          'staticIP=True and natIP cannot be specified at the same time')
    if static_ip:
      address_resource, nat_ip = MakeStaticAddress(vm_name, zone)
      resource.append(address_resource)
    if nat_ip:
      access_config['natIP'] = nat_ip
  else:
    if static_ip:
      raise common.Error('staticIP cannot be True when hasExternalIP is False')
    if nat_ip:
      raise common.Error(
          'natIP must not be specified when hasExternalIP is False')

  network_interfaces = []
  if subnetwork:
    network_interfaces.insert(0, {
        'network': network,
        'subnetwork': subnetwork,
        'accessConfigs': access_configs
    })
  else:
    network_interfaces.insert(0, {
        'network': network,
        'accessConfigs': access_configs
    })

  resource.insert(0, {
      'name': vm_name,
      'type': default.INSTANCE,
      'properties': {
          'zone': zone,
          'machineType': machine_type,
          'canIpForward': can_ip_fwd,
          'disks': disks,
          'networkInterfaces': network_interfaces,
          'tags': tags,
          'metadata': metadata,
      }
  })

  # Pass through any additional properties to the VM
  if SERVICE_ACCOUNTS in prop:
    resource[0]['properties'].update({SERVICE_ACCOUNTS: prop[SERVICE_ACCOUNTS]})
  if GUEST_ACCELERATORS in prop:
    for accelerators in prop[GUEST_ACCELERATORS]:
      accelerators['acceleratorType'] = common.MakeAcceleratorTypeLink(
          context, accelerators['acceleratorType'])
    resource[0]['properties'].update(
        {GUEST_ACCELERATORS: prop[GUEST_ACCELERATORS]})
    # GPUs cannot be attached to live migratable instances. See:
    # https://cloud.google.com/compute/docs/gpus/#restrictions
    resource[0]['properties'].update(
        {'scheduling': {'onHostMaintenance': 'terminate'}})
  return resource
Example #2
0
def generate_config(context):
    """Creates the gateway."""
    prop = context.properties
    prop['cloudguardVersion'], _, prop['installationType'] = prop[
        'installationType'].partition(' ')
    prop['templateName'] = TEMPLATE_NAME
    prop['templateVersion'] = TEMPLATE_VERSION
    prop['allowUploadDownload'] = str(prop['allowUploadDownload']).lower()
    if not prop['managementGUIClientNetwork'] and prop['installationType'] in {
            'Gateway and Management (Standalone)', 'Management only'
    }:
        raise Exception('Allowed GUI clients are required when installing '
                        'a management server')
    for k in ['managementGUIClientNetwork']:
        prop.setdefault(k, '')
    resources = []
    outputs = []
    network_interfaces = []
    external_ifs = []
    zone = prop['zone']
    deployment = context.env['deployment']
    vm_name = set_name_and_truncate(deployment, '-vm')
    access_configs = []
    if prop['externalIP'] != 'None':
        access_config = make_access_config(resources, vm_name, zone,
                                           'Static' == prop['externalIP'])
        access_configs.append(access_config)
        external_ifs.append(0)
        prop['hasInternet'] = 'true'
    else:
        prop['hasInternet'] = 'false'
    network = common.MakeGlobalComputeLink(context, default.NETWORK)
    networks = {prop['network']}
    network_interface = {
        'network': network,
        'accessConfigs': access_configs,
    }
    if default.SUBNETWORK in prop:
        network_interface['subnetwork'] = common.MakeSubnetworkComputeLink(
            context, default.SUBNETWORK)
    network_interfaces.append(network_interface)
    for ifnum in range(1, prop['numAdditionalNICs'] + 1):
        net = prop.get(ADDITIONAL_NETWORK.format(ifnum))
        subnet = prop.get(ADDITIONAL_SUBNET.format(ifnum))
        ext_ip = prop.get(ADDITIONAL_EXTERNAL_IP.format(ifnum))
        if not net or not subnet:
            raise Exception(
                'Missing network parameters for interface {}'.format(ifnum))
        if net in networks:
            raise Exception('Cannot use network "' + net + '" more than once')
        networks.add(net)
        net = ''.join([
            default.COMPUTE_URL_BASE, 'projects/', context.env['project'],
            '/global/networks/', net
        ])
        subnet = ''.join([
            default.COMPUTE_URL_BASE, 'projects/', context.env['project'],
            '/regions/',
            common.ZoneToRegion(zone), '/subnetworks/', subnet
        ])
        network_interface = {
            'network': net,
            'subnetwork': subnet,
        }
        if 'None' != ext_ip:
            external_ifs.append(ifnum)
            access_config = make_access_config(resources, vm_name, zone,
                                               'Static' == ext_ip, ifnum + 1)
            access_configs = [access_config]
            network_interface['accessConfigs'] = access_configs
            if not prop.get('hasInternet') or 'false' == prop['hasInternet']:
                prop['hasInternet'] = 'true'
        network_interfaces.append(network_interface)
    for ifnum in range(prop['numAdditionalNICs'] + 1, MAX_NICS):
        prop.pop(ADDITIONAL_NETWORK.format(ifnum), None)
        prop.pop(ADDITIONAL_SUBNET.format(ifnum), None)
        prop.pop(ADDITIONAL_EXTERNAL_IP.format(ifnum), None)
    deployment_config = set_name_and_truncate(deployment, '-config')
    prop['config_url'] = ('https://runtimeconfig.googleapis.com/v1beta1/' +
                          'projects/' + context.env['project'] + '/configs/' +
                          deployment_config)
    prop['config_path'] = '/'.join(prop['config_url'].split('/')[-4:])
    prop['deployment_config'] = deployment_config
    tags = ATTRIBUTES[prop['installationType']]['tags']
    uid = set_name_and_truncate(
        vm_name, '-' + password.GeneratePassword(8, False).lower())
    if prop['installationType'] == 'Gateway only':
        prop['cloudguardVersion'] += '-GW'
        if not prop.get('sicKey'):
            prop['computed_sic_key'] = password.GeneratePassword(12, False)
        else:
            prop['computed_sic_key'] = prop['sicKey']
    else:
        prop['computed_sic_key'] = 'N/A'
    outputs.append({
        'name': 'sicKey',
        'value': prop['computed_sic_key'],
    }, )
    if 'gw' in VERSIONS[prop['cloudguardVersion']]:
        license_name = "{}-{}".format(LICENSE, LICENCE_TYPE)
    else:
        license_name = LICENSE
    family = '-'.join(
        ['check-point', VERSIONS[prop['cloudguardVersion']], license_name])
    formatter = common.DefaultFormatter()
    gw = {
        'type': default.INSTANCE,
        'name': vm_name,
        'properties': {
            'description':
            ATTRIBUTES[prop['installationType']]['description'],
            'zone':
            zone,
            'tags': {
                'items': tags + [uid],
            },
            'machineType':
            common.MakeLocalComputeLink(context, default.MACHINETYPE),
            'canIpForward':
            ATTRIBUTES[prop['installationType']]['canIpForward'],
            'networkInterfaces':
            network_interfaces,
            'disks': [{
                'autoDelete':
                True,
                'boot':
                True,
                'deviceName':
                common.AutoName(context.env['name'], default.DISK, 'boot'),
                'initializeParams': {
                    'diskType':
                    common.MakeLocalComputeLink(context, default.DISKTYPE),
                    'diskSizeGb':
                    prop['bootDiskSizeGb'],
                    'sourceImage':
                    'projects/%s/global/images/%s' %
                    (PROJECT, images.IMAGES[family]),
                },
                'type':
                'PERSISTENT',
            }],
            'metadata': {
                'items': [
                    {
                        'key': 'startup-script',
                        'value': formatter.format(startup_script, **prop)
                    },
                ]
            },
            'serviceAccounts': [{
                'email':
                'default',
                'scopes': ['https://www.googleapis.com/auth/monitoring.write'],
            }]
        }
    }
    if (prop['externalIP'] != 'None') and ('Manual Configuration' !=
                                           prop['installationType']):
        gw['properties']['serviceAccounts'][0]['scopes'].append(
            'https://www.googleapis.com/auth/cloudruntimeconfig')
        resources.append({
            'name': deployment_config,
            'type': 'runtimeconfig.v1beta1.config',
            'properties': {
                'config':
                deployment_config,
                'description': ('Holds software readiness status '
                                'for deployment {}').format(deployment),
            },
        })
        resources.append({
            'name': set_name_and_truncate(deployment, '-software'),
            'type': 'runtimeconfig.v1beta1.waiter',
            'metadata': {
                'dependsOn': [],
            },
            'properties': {
                'parent': '$(ref.' + deployment_config + '.name)',
                'waiter': 'software',
                'timeout': '1800s',
                'success': {
                    'cardinality': {
                        'number': 1,
                        'path': 'status/success',
                    },
                },
                'failure': {
                    'cardinality': {
                        'number': 1,
                        'path': 'status/failure',
                    },
                },
            },
        })
    if 'instanceSSHKey' in prop:
        gw['properties']['metadata']['items'].append({
            'key':
            'instanceSSHKey',
            'value':
            prop['instanceSSHKey']
        })
    if prop['generatePassword']:
        passwd = password.GeneratePassword(12, False)
        gw['properties']['metadata']['items'].append({
            'key': 'adminPasswordSourceMetadata',
            'value': passwd
        })
    else:
        passwd = ''
    resources.append(gw)
    netlist = list(networks)
    if GATEWAY in tags:
        for i in range(len(netlist)):
            network = netlist[i]
            fw_rule_name_prefix = set_name_and_truncate(
                '{}-{}'.format(deployment[:23], network[:18]),
                '-allow-all-to-chkp-{}'.format(i + 1))
            firewall_rules = create_firewall_rules(prop, network,
                                                   fw_rule_name_prefix)
            resources.extend(firewall_rules)
    elif MANAGEMENT in tags:
        for i in range(len(netlist)):
            network = netlist[i]
            source_ranges = prop['network_tcpSourceRanges']
            tcp_enabled = prop['network_enableTcp']
            gwNetwork_enabled = prop['network_enableGwNetwork']
            gwNetwork_source_range = prop['network_gwNetworkSourceRanges']
            if source_ranges and not tcp_enabled:
                raise Exception(
                    'Allowed source IP ranges for TCP traffic are provided '
                    'but TCP not marked as allowed')
            if tcp_enabled and not source_ranges:
                raise Exception('Allowed source IP ranges for TCP traffic'
                                ' are required when installing '
                                'a management server')
            if not gwNetwork_enabled and gwNetwork_source_range:
                raise Exception('Gateway network source IP are provided but '
                                'not marked as allowed.')
            if gwNetwork_enabled and not gwNetwork_source_range:
                raise Exception('Gateway network source IP is required in'
                                ' MGMT deployment.')
            ranges_list = source_ranges.split(',')
            gw_network_list = gwNetwork_source_range.split(',')
            ranges = []
            gw_net_ranges = []
            for source_range in ranges_list:
                ranges.append(source_range.replace(" ", ""))
            for gw_net_range in gw_network_list:
                gw_net_ranges.append(gw_net_range.replace(" ", ""))
            if tcp_enabled:
                if gwNetwork_enabled:
                    resources.append({
                        'type':
                        'compute.v1.firewall',
                        'name':
                        set_name_and_truncate(
                            '{}-{}'.format(deployment[:23], network[:18]),
                            '-gateways-to-management-{}'.format(i + 1)),
                        'properties': {
                            'network':
                            'global/networks/' + network,
                            'sourceRanges':
                            list(set(gw_net_ranges + ranges)),
                            'sourceTags': [GATEWAY],
                            'targetTags': [uid],
                            'allowed': [
                                {
                                    'IPProtocol': 'tcp',
                                    'ports':
                                    ['257', '18191', '18210', '18264']
                                },
                            ],
                        }
                    })
                resources.append({
                    'type':
                    'compute.v1.firewall',
                    'name':
                    set_name_and_truncate(
                        '{}-{}'.format(deployment[:23], network[:18]),
                        '-allow-gui-clients-{}'.format(i + 1)),
                    'properties': {
                        'network':
                        'global/networks/' + network,
                        'sourceRanges':
                        list(set(ranges)),
                        'targetTags': [uid],
                        'allowed': [
                            {
                                'IPProtocol': 'tcp',
                                'ports': ['22', '443', '18190', '19009']
                            },
                        ],
                    }
                })
            fw_rule_name_prefix = set_name_and_truncate(
                '{}-{}'.format(deployment[:23], network[:18]),
                '-allow-all-to-chkp-{}'.format(i + 1))
            firewall_rules = create_firewall_rules(prop, network,
                                                   fw_rule_name_prefix, True,
                                                   uid)
            resources.extend(firewall_rules)
    outputs += [{
        'name': 'deployment',
        'value': deployment
    }, {
        'name': 'project',
        'value': context.env['project']
    }, {
        'name': 'vmName',
        'value': vm_name,
    }, {
        'name': 'vmId',
        'value': '$(ref.%s.id)' % vm_name,
    }, {
        'name': 'vmSelfLink',
        'value': '$(ref.%s.selfLink)' % vm_name,
    }, {
        'name': 'hasMultiExternalIPs',
        'value': 0 < len(external_ifs) and external_ifs != [0],
    }, {
        'name':
        'additionalExternalIPs',
        'value':
        ', '.join([('$(ref.{}.networkInterfaces[{}].' +
                    'accessConfigs[0].natIP)').format(vm_name, ifnum)
                   for ifnum in external_ifs if ifnum])
    }, {
        'name': 'vmInternalIP',
        'value': '$(ref.%s.networkInterfaces[0].networkIP)' % vm_name,
    }, {
        'name': 'password',
        'value': passwd
    }]
    return common.MakeResource(resources, outputs)
def make_gw(context, name, zone, nics, passwd=None, depends_on=None):
    cg_version = context.properties['ha_version'].split(' ')[0]
    family = '-'.join(['check-point', VERSIONS[cg_version], LICENSE])
    formatter = common.DefaultFormatter()

    gw = {
        'type': default.INSTANCE,
        'name': name,
        'metadata': {
            'dependsOn': depends_on
        },
        'properties': {
            'description': 'CloudGuard Highly Available Security Cluster',
            'zone': zone,
            'tags': {
                'items': [GATEWAY],
            },
            'machineType': common.MakeLocalComputeLink(
                context, default.MACHINETYPE, zone),
            'canIpForward': True,
            'networkInterfaces': nics,
            'disks': [{
                'autoDelete': True,
                'boot': True,
                'deviceName': common.set_name_and_truncate(
                    context.properties['deployment'],
                    '-{}-boot'.format(name)),
                'initializeParams': {
                    'diskType': common.MakeLocalComputeLink(
                        context, default.DISKTYPE, zone),
                    'diskSizeGb': context.properties['bootDiskSizeGb'],
                    'sourceImage':
                        'projects/%s/global/images/%s' % (
                            PROJECT, images.IMAGES[family]),
                },
                'type': 'PERSISTENT',
            }],
            'metadata': {
                'items': [
                    {
                        'key': 'startup-script',
                        'value': formatter.format(
                            startup_script, **context.properties)
                    }
                ]
            },
            'serviceAccounts': [{
                'email': 'default',
                'scopes': [
                    'https://www.googleapis.com/auth/monitoring.write',
                    'https://www.googleapis.com/auth/compute',
                    'https://www.googleapis.com/auth/cloudruntimeconfig'
                ],
            }]
        }
    }

    if context.properties['instanceSSHKey']:
        gw['properties']['metadata']['items'].append(
            {
                'key': 'instanceSSHKey',
                'value': context.properties['instanceSSHKey']
            }
        )

    if passwd:
        gw['properties']['metadata']['items'].append(
            {
                'key': 'adminPasswordSourceMetadata',
                'value': passwd
            }
        )

    return gw
def GenerateComputeVM(context):
    """Generates one VM instance resource."""
    prop = context.properties
    boot_disk_type = prop.setdefault(BOOTDISKTYPE, DEFAULT_DISKTYPE)
    prop[default.DISKTYPE] = boot_disk_type
    can_ip_fwd = prop.setdefault(CAN_IP_FWD, DEFAULT_IP_FWD)
    disks = prop.setdefault(default.DISKS, list())
    local_ssd = prop.setdefault(default.LOCAL_SSD, 0)
    # Temporary alternative while multiple disks on creation is not allowed
    if disks:
        new_disks = prop.setdefault(default.DISK_RESOURCES, list())
        disks, prop[DISK_RESOURCES] = GenerateDisks(context, disks, new_disks)
    machine_type = prop.setdefault(MACHINETYPE, DEFAULT_MACHINETYPE)
    metadata = prop.setdefault(METADATA, dict())
    network = prop.setdefault(NETWORK, DEFAULT_NETWORK)
    vm_name = MakeVMName(context)
    provide_boot = prop.setdefault(PROVIDE_BOOT, DEFAULT_PROVIDE_BOOT)
    tags = prop.setdefault(TAGS, dict([('items', [])]))
    zone = prop.setdefault(ZONE, DEFAULT_ZONE)
    has_external_ip = prop.get(HAS_EXTERNAL_IP, DEFAULT_HAS_EXTERNAL_IP)
    static_ip = prop.get(STATIC_IP, DEFAULT_STATIC_IP)
    nat_ip = prop.get(NAT_IP, None)
    if provide_boot:
        dev_mode = DEVIMAGE in prop and prop[DEVIMAGE]
        src_image = common.MakeC2DImageLink(prop[SRCIMAGE], dev_mode)
        boot_name = common.AutoName(context.env['name'], default.DISK, 'boot')
        disk_size = prop.get(BOOTDISKSIZE, DEFAULT_BOOTDISKSIZE)
        disk_type = common.MakeLocalComputeLink(context, DISKTYPE)
        autodelete = prop.get(AUTODELETE_BOOTDISK, DEFAULT_AUTODELETE_BOOTDISK)
        disks = PrependBootDisk(disks, boot_name, disk_type, disk_size,
                                src_image, autodelete)
    if local_ssd:
        disks = AppendLocalSSDDisks(context, disks, local_ssd)
    machine_type = common.MakeLocalComputeLink(context, default.MACHINETYPE)
    network = common.MakeGlobalComputeLink(context, default.NETWORK)
    subnetwork = ''
    if default.SUBNETWORK in prop:
        subnetwork = common.MakeSubnetworkComputeLink(context,
                                                      default.SUBNETWORK)

    # To be consistent with Dev console and gcloud, service accounts need to be
    #  explicitly disabled
    remove_scopes = prop[NO_SCOPE] if NO_SCOPE in prop else False
    if remove_scopes and SERVICE_ACCOUNTS in prop:
        prop.pop(SERVICE_ACCOUNTS)
    else:  # Make sure there is a default service account
        prop.setdefault(SERVICE_ACCOUNTS,
                        copy.deepcopy(DEFAULT_SERVICE_ACCOUNT))

    resource = []

    access_configs = []
    if has_external_ip:
        access_config = {'name': default.EXTERNAL, 'type': default.ONE_NAT}
        access_configs.append(access_config)
        if static_ip and nat_ip:
            raise common.Error(
                'staticIP=True and natIP cannot be specified at the same time')
        if static_ip:
            address_resource, nat_ip = MakeStaticAddress(vm_name, zone)
            resource.append(address_resource)
        if nat_ip:
            access_config['natIP'] = nat_ip
    else:
        if static_ip:
            raise common.Error(
                'staticIP cannot be True when hasExternalIP is False')
        if nat_ip:
            raise common.Error(
                'natIP must not be specified when hasExternalIP is False')

    network_interfaces = []
    if subnetwork:
        network_interfaces.insert(
            0, {
                'network': network,
                'subnetwork': subnetwork,
                'accessConfigs': access_configs
            })
    else:
        network_interfaces.insert(0, {
            'network': network,
            'accessConfigs': access_configs
        })

    resource.insert(
        0, {
            'name': vm_name,
            'type': default.INSTANCE,
            'properties': {
                'zone': zone,
                'machineType': machine_type,
                'canIpForward': can_ip_fwd,
                'disks': disks,
                'networkInterfaces': network_interfaces,
                'tags': tags,
                'metadata': metadata,
            }
        })

    # Pass through any additional property to the VM
    if SERVICE_ACCOUNTS in prop:
        resource[0]['properties'].update(
            {SERVICE_ACCOUNTS: prop[SERVICE_ACCOUNTS]})
    return resource
Example #5
0
def GenerateComputeVM(context, create_disks_separately=True):
    """Generates one VM instance resource.

  Args:
    context: Template context dictionary.
    create_disks_separately: When true (default), all new disk resources are
      created as separate resources. This is legacy behaviour from when multiple
      disks creation was not allowed in the disks property.
  Returns:
    dictionary representing instance resource.
  """
    prop = context.properties
    boot_disk_type = prop.setdefault(BOOTDISKTYPE, DEFAULT_DISKTYPE)
    prop[default.DISKTYPE] = boot_disk_type
    can_ip_fwd = prop.setdefault(CAN_IP_FWD, DEFAULT_IP_FWD)
    disks = prop.setdefault(default.DISKS, list())
    local_ssd = prop.setdefault(default.LOCAL_SSD, 0)

    if disks:
        if create_disks_separately:
            # Legacy alternative from when multiple disks on creation were not allowed
            new_disks = prop.setdefault(default.DISK_RESOURCES, list())
            SetDiskProperties(context, disks)
            disks, prop[DISK_RESOURCES] = GenerateDisks(
                context, disks, new_disks)
        else:
            # All new disks (except local ssd) must provide a sourceImage or existing
            # source. Add blank source image if non provided.
            SetDiskProperties(context, disks, add_blank_src_img=True)

    machine_type = prop.setdefault(MACHINETYPE, DEFAULT_MACHINETYPE)
    metadata = prop.setdefault(METADATA, dict())
    SetMetadataDefaults(metadata)
    vm_name = MakeVMName(context)
    provide_boot = prop.setdefault(PROVIDE_BOOT, DEFAULT_PROVIDE_BOOT)
    tags = prop.setdefault(TAGS, dict([("items", [])]))
    zone = prop.setdefault(ZONE, DEFAULT_ZONE)

    if provide_boot:
        dev_mode = DEVIMAGE in prop and prop[DEVIMAGE]
        src_image = common.MakeC2DImageLink(prop[SRCIMAGE], dev_mode)
        boot_name = common.AutoName(context.env["name"], default.DISK, "boot")
        disk_size = prop.get(BOOTDISKSIZE, DEFAULT_BOOTDISKSIZE)
        disk_type = common.MakeLocalComputeLink(context, DISKTYPE)
        autodelete = prop.get(AUTODELETE_BOOTDISK, DEFAULT_AUTODELETE_BOOTDISK)
        disks = PrependBootDisk(disks, boot_name, disk_type, disk_size,
                                src_image, autodelete)
    if local_ssd:
        disks = AppendLocalSSDDisks(context, disks, local_ssd)
    machine_type = common.MakeLocalComputeLink(context, default.MACHINETYPE)

    # To be consistent with Dev console and gcloud, service accounts need to be
    #  explicitly disabled
    remove_scopes = prop[NO_SCOPE] if NO_SCOPE in prop else False
    if remove_scopes and SERVICE_ACCOUNTS in prop:
        prop.pop(SERVICE_ACCOUNTS)
    else:  # Make sure there is a default service account
        prop.setdefault(SERVICE_ACCOUNTS,
                        copy.deepcopy(DEFAULT_SERVICE_ACCOUNT))

    resource = []
    resource.insert(
        0,
        {
            "name": vm_name,
            "type": default.INSTANCE,
            "properties": {
                "zone": zone,
                "machineType": machine_type,
                "canIpForward": can_ip_fwd,
                "disks": disks,
                "networkInterfaces": GetNetworkInterfaces(context),
                "tags": tags,
                "metadata": metadata,
            },
        },
    )

    # Pass through any additional properties to the VM
    if SERVICE_ACCOUNTS in prop:
        resource[0]["properties"].update(
            {SERVICE_ACCOUNTS: prop[SERVICE_ACCOUNTS]})
    if GUEST_ACCELERATORS in prop:
        for accelerators in prop[GUEST_ACCELERATORS]:
            accelerators["acceleratorType"] = common.MakeAcceleratorTypeLink(
                context, accelerators["acceleratorType"])
        resource[0]["properties"].update(
            {GUEST_ACCELERATORS: prop[GUEST_ACCELERATORS]})
        # GPUs cannot be attached to live migratable instances. See:
        # https://cloud.google.com/compute/docs/gpus/#restrictions
        resource[0]["properties"].update(
            {"scheduling": {
                "onHostMaintenance": "terminate"
            }})
    return resource
def GenerateComputeVM(context):
    """Generates one VM instance resource."""
    name = context.env['name']
    prop = context.properties
    if SRCIMAGE not in prop:
        raise common.Error('"%s" is a mandatory property' % SRCIMAGE)
    boot_disk_type = prop.setdefault(BOOTDISKTYPE, DEFAULT_DISKTYPE)
    prop[default.DISKTYPE] = boot_disk_type
    can_ip_fwd = prop.setdefault(CAN_IP_FWD, DEFAULT_IP_FWD)
    disks = prop.setdefault(default.DISKS, list())
    # Temporary alternative while multiple disks on creation is not allowed
    if disks:
        new_disks = prop.setdefault(default.DISK_RESOURCES, list())
        disks, prop[DISK_RESOURCES] = GenerateDisks(context, disks, new_disks)
    machine_type = prop.setdefault(MACHINETYPE, DEFAULT_MACHINETYPE)
    metadata = prop.setdefault(METADATA, dict())
    network = prop.setdefault(NETWORK, DEFAULT_NETWORK)
    named = INSTANCE_NAME in prop
    provide_boot = prop.setdefault(PROVIDE_BOOT, DEFAULT_PROVIDE_BOOT)
    tags = prop.setdefault(TAGS, dict([('items', [])]))
    vm_name = prop[INSTANCE_NAME] if named else common.AutoName(
        name, default.INSTANCE)
    zone = prop.setdefault(ZONE, DEFAULT_ZONE)
    if provide_boot:
        dev_mode = DEVIMAGE in prop and prop[DEVIMAGE]
        src_image = common.MakeC2DImageLink(prop[SRCIMAGE], dev_mode)
        boot_name = common.AutoName(context.env['name'], default.DISK, 'boot')
        disk_size = (prop[BOOTDISKSIZE]
                     if BOOTDISKSIZE in prop else DEFAULT_BOOTDISKSIZE)
        disk_type = common.MakeLocalComputeLink(context, default.DISKTYPE)
        disks = PrependBootDisk(disks, boot_name, disk_type, disk_size,
                                src_image)
    machine_type = common.MakeLocalComputeLink(context, default.MACHINETYPE)
    network = common.MakeGlobalComputeLink(context, default.NETWORK)
    # To be consistent with Dev console and gcloud, service accounts need to be
    #  explicitly disabled
    remove_scopes = prop[NO_SCOPE] if NO_SCOPE in prop else False
    if remove_scopes and SERVICE_ACCOUNTS in prop:
        prop.pop(SERVICE_ACCOUNTS)
    else:  # Make sure there is a default service account
        prop.setdefault(SERVICE_ACCOUNTS,
                        copy.deepcopy(DEFAULT_SERVICE_ACCOUNT))

    # pyformat: disable
    resource = [{
        'name': vm_name,
        'type': default.INSTANCE,
        'properties': {
            'zone':
            zone,
            'machineType':
            machine_type,
            'canIpForward':
            can_ip_fwd,
            'disks':
            disks,
            'networkInterfaces': [{
                'network':
                network,
                'accessConfigs': [{
                    'name': default.EXTERNAL,
                    'type': default.ONE_NAT
                }]
            }],
            'tags':
            tags,
            'metadata':
            metadata,
        }
    }]
    # pyformat: enable

    # Pass through any additional property to the VM
    if SERVICE_ACCOUNTS in prop:
        resource[0]['properties'].update(
            {SERVICE_ACCOUNTS: prop[SERVICE_ACCOUNTS]})
    return resource
Example #7
0
def GenerateComputeVM(context, create_disks_separately=True):
  """Generates one VM instance resource.

  Args:
    context: Template context dictionary.
    create_disks_separately: When true (default), all new disk resources are
      created as separate resources. This is legacy behaviour from when multiple
      disks creation was not allowed in the disks property.
  Returns:
    dictionary representing instance resource.
  """
  prop = context.properties
  boot_disk_type = prop.setdefault(BOOTDISKTYPE, DEFAULT_DISKTYPE)
  prop[default.DISKTYPE] = boot_disk_type
  can_ip_fwd = prop.setdefault(CAN_IP_FWD, DEFAULT_IP_FWD)
  disks = prop.setdefault(default.DISKS, list())
  local_ssd = prop.setdefault(default.LOCAL_SSD, 0)
  project = context.env[default.PROJECT]
  deployApiToGke = context.properties['deployApiToGke']
  datashare_install_bucket_name = project + '-install-bucket'
  datashare_ingestion_bucket_name = project + '-cds-bucket'
  k8s_cluster_name = 'datashare-cluster-resource'
  # gce_service_account = context.properties['gceServiceAccount']

  if disks:
    if create_disks_separately:
      # Legacy alternative from when multiple disks on creation were not allowed
      new_disks = prop.setdefault(default.DISK_RESOURCES, list())
      SetDiskProperties(context, disks)
      disks, prop[DISK_RESOURCES] = GenerateDisks(context, disks, new_disks)
    else:
      # All new disks (except local ssd) must provide a sourceImage or existing
      # source. Add blank source image if non provided.
      SetDiskProperties(context, disks, add_blank_src_img=True)

  machine_type = prop.setdefault(MACHINETYPE, DEFAULT_MACHINETYPE)
  metadata = prop.setdefault(METADATA, dict())
  SetMetadataDefaults(metadata)
  vm_name = MakeVMName(context)
  provide_boot = prop.setdefault(PROVIDE_BOOT, DEFAULT_PROVIDE_BOOT)
  tags = prop.setdefault(TAGS, dict([('items', [])]))
  zone = prop.setdefault(ZONE, DEFAULT_ZONE)

  if provide_boot:
    dev_mode = DEVIMAGE in prop and prop[DEVIMAGE]
    src_image = common.MakeC2DImageLink(prop[SRCIMAGE], dev_mode)
    boot_name = common.AutoName(context.env['name'], default.DISK, 'boot')
    disk_size = prop.get(BOOTDISKSIZE, DEFAULT_BOOTDISKSIZE)
    disk_type = common.MakeLocalComputeLink(context, DISKTYPE)
    autodelete = prop.get(AUTODELETE_BOOTDISK, DEFAULT_AUTODELETE_BOOTDISK)
    disks = PrependBootDisk(disks, boot_name, disk_type, disk_size, src_image,
                            autodelete)
  if local_ssd:
    disks = AppendLocalSSDDisks(context, disks, local_ssd)
  machine_type = common.MakeLocalComputeLink(context, default.MACHINETYPE)

  # To be consistent with Dev console and gcloud, service accounts need to be
  #  explicitly disabled
  remove_scopes = prop[NO_SCOPE] if NO_SCOPE in prop else False
  if remove_scopes and SERVICE_ACCOUNTS in prop:
    prop.pop(SERVICE_ACCOUNTS)
  else:  # Make sure there is a default service account
    prop.setdefault(SERVICE_ACCOUNTS, copy.deepcopy(DEFAULT_SERVICE_ACCOUNT))

  resource = []
  resource.insert(
      0, {
          'name': vm_name,
          'type': default.INSTANCE,
          'metadata': {
              'dependsOn': [ 
                datashare_ingestion_bucket_name
              ]
          },
          'properties': {
              'zone': zone,
              'machineType': machine_type,
              'canIpForward': can_ip_fwd,
              'disks': disks,
              'networkInterfaces': GetNetworkInterfaces(context),
              'tags': tags,
              'metadata': metadata,
          }
      })
  if deployApiToGke: 
      resource[0]['metadata']['dependsOn'].append(k8s_cluster_name)

  if context.properties['useRuntimeConfigWaiter']:
    configName = context.properties['waiterConfigName']
    resource[0]['metadata']['dependsOn'].append(configName)
    resource[0]['metadata']['dependsOn'].append(datashare_install_bucket_name)

  # Pass through any additional properties to the VM
  if SERVICE_ACCOUNTS in prop:
    resource[0]['properties'].update({SERVICE_ACCOUNTS: prop[SERVICE_ACCOUNTS]})
  if GUEST_ACCELERATORS in prop:
    for accelerators in prop[GUEST_ACCELERATORS]:
      accelerators['acceleratorType'] = common.MakeAcceleratorTypeLink(
          context, accelerators['acceleratorType'])
    resource[0]['properties'].update(
        {GUEST_ACCELERATORS: prop[GUEST_ACCELERATORS]})
    # GPUs cannot be attached to live migratable instances. See:
    # https://cloud.google.com/compute/docs/gpus/#restrictions
    resource[0]['properties'].update(
        {'scheduling': {'onHostMaintenance': 'terminate'}})
  return resource