Skip to content

Commit

Permalink
[DM] Instance and Instance Template support multiple NICs (#31)
Browse files Browse the repository at this point in the history
Support for a list of networks where the machine needs to be connected.
  • Loading branch information
alexkonkin authored and ocsig committed May 22, 2019
1 parent 6b8b714 commit fc452a8
Show file tree
Hide file tree
Showing 14 changed files with 895 additions and 139 deletions.
3 changes: 2 additions & 1 deletion dm/templates/instance/examples/instance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ resources:
diskImage: projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-lts
machineType: f1-micro
diskType: pd-ssd
network: default
networks:
- name: default
metadata:
items:
- key: startup-script
Expand Down
73 changes: 38 additions & 35 deletions dm/templates/instance/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,46 @@ def create_boot_disk(properties, zone, instance_name):

return boot_disk

def get_network(properties):
def get_network_interfaces(properties):
""" Get the configuration that connects the instance to an existing network
and assigns to it an ephemeral public IP.
and assigns to it an ephemeral public IP if specified.
"""

network_name = properties.get('network')

if not '.' in network_name and not '/' in network_name:
network_name = 'global/networks/{}'.format(network_name)

network_interfaces = {
'network': network_name,
}

if properties['hasExternalIp']:
access_configs = {
'name': 'External NAT',
'type': 'ONE_TO_ONE_NAT'
network_interfaces = []

networks = properties.get('networks', [{
"name": properties.get('network'),
"hasExternalIp": properties.get('hasExternalIp'),
"natIP": properties.get('natIP'),
"subnetwork": properties.get('subnetwork'),
"networkIP": properties.get('networkIP'),
}])

for network in networks:
if not '.' in network['name'] and not '/' in network['name']:
network_name = 'global/networks/{}'.format(network['name'])
else:
network_name = network['name']

network_interface = {
'network': network_name,
}

if 'natIP' in properties:
access_configs['natIP'] = properties['natIP']
if network['hasExternalIp']:
access_configs = {
'name': 'External NAT',
'type': 'ONE_TO_ONE_NAT'
}

if network.get('natIP'):
access_configs['natIP'] = network['natIP']

network_interfaces['accessConfigs'] = [access_configs]
network_interface['accessConfigs'] = [access_configs]

netif_optional_props = ['subnetwork', 'networkIP']
for prop in netif_optional_props:
if prop in properties:
network_interfaces[prop] = properties[prop]
netif_optional_props = ['subnetwork', 'networkIP']
for prop in netif_optional_props:
if network.get(prop):
network_interface[prop] = network[prop]
network_interfaces.append(network_interface)

return network_interfaces

Expand All @@ -84,7 +95,7 @@ def generate_config(context):
machine_type = context.properties['machineType']

boot_disk = create_boot_disk(context.properties, zone, vm_name)
network = get_network(context.properties)
network_interfaces = get_network_interfaces(context.properties)
instance = {
'name': vm_name,
'type': 'compute.v1.instance',
Expand All @@ -93,7 +104,7 @@ def generate_config(context):
'machineType': 'zones/{}/machineTypes/{}'.format(zone,
machine_type),
'disks': [boot_disk],
'networkInterfaces': [network]
'networkInterfaces': network_interfaces
}
}

Expand All @@ -102,8 +113,8 @@ def generate_config(context):

outputs = [
{
'name': 'internalIp',
'value': '$(ref.{}.networkInterfaces[0].networkIP)'.format(vm_name) # pylint: disable=line-too-long
'name': 'networkInterfaces',
'value': '$(ref.{}.networkInterfaces)'.format(vm_name)
},
{
'name': 'name',
Expand All @@ -115,12 +126,4 @@ def generate_config(context):
}
]

if context.properties['hasExternalIp']:
outputs.append(
{
'name': 'externalIp',
'value': '$(ref.{}.networkInterfaces[0].accessConfigs[0].natIP)'.format(vm_name) # pylint: disable=line-too-long
}
)

return {'resources': [instance], 'outputs': outputs}
149 changes: 110 additions & 39 deletions dm/templates/instance/instance.py.schema
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,69 @@ required:
- zone
- machineType
- diskImage
- network

oneOf:
- allOf:
- required:
- networks
- properties:
networks:
minItems: 1
- not:
required:
- network
- not:
required:
- natIP
- not:
required:
- subnetwork
- not:
required:
- networkIP
- allOf:
- required:
- network
- not:
required:
- networks

additionalProperties: false

definitions:
hasExternalIp:
type: boolean
default: true
description: |
Defines wether the instance will use an external IP from a shared
ephemeral IP address pool. If this is set to false, the instance
will not have an external IP.
natIP:
type: string
description: |
An external IP address associated with this instance. Specify an unused
static external IP address available to the project or leave this field
undefined to use an IP from a shared ephemeral IP address pool. If you
specify a static external IP address, it must live in the same region
as the zone of the instance.
If hasExternalIp is false this field is ignored.
subnetwork:
type: string
description: |
The URL of the Subnetwork resource for this instance. If the network
resource is in legacy mode, do not provide this property. If the network
is in auto subnet mode, providing the subnetwork is optional. If the
network is in custom subnet mode, then this field should be specified.
If you specify this property, you can specify the subnetwork as a full
or partial URL. For example, the following are all valid URLs:
- https://www.googleapis.com/compute/v1/projects/project/regions/region/subnetworks/subnetwork
- regions/region/subnetworks/subnetwork
networkIP:
type: string
description: |
An IPv4 internal network address to assign to the instance for this
network interface. If not specified by the user, an unused internal IP
is assigned by the system.

properties:
name:
Expand All @@ -36,42 +98,41 @@ properties:
description: |
Name of the network the instance will be connected to;
e.g., 'my-custom-network' or 'default'.
zone:
type: string
description: Availability zone. E.g. 'us-central1-a'
hasExternalIp:
type: boolean
default: true
description: |
Defines wether the instance will use an external IP from a shared
ephemeral IP address pool. If this is set to false, the instance
will not have an external IP.
$ref: '#/definitions/hasExternalIp'
natIP:
type: string
description: |
An external IP address associated with this instance. Specify an unused
static external IP address available to the project or leave this field
undefined to use an IP from a shared ephemeral IP address pool. If you
specify a static external IP address, it must live in the same region
as the zone of the instance.
If hasExternalIp is false this field is ignored.
$ref: '#/definitions/natIP'
subnetwork:
type: string
description: |
The URL of the Subnetwork resource for this instance. If the network
resource is in legacy mode, do not provide this property. If the network
is in auto subnet mode, providing the subnetwork is optional. If the
network is in custom subnet mode, then this field should be specified.
If you specify this property, you can specify the subnetwork as a full
or partial URL. For example, the following are all valid URLs:
- https://www.googleapis.com/compute/v1/projects/project/regions/region/subnetworks/subnetwork
- regions/region/subnetworks/subnetwork
$ref: '#/definitions/subnetwork'
networkIP:
type: string
$ref: '#/definitions/networkIP'
networks:
type: array
description: |
An IPv4 internal network address to assign to the instance for this
network interface. If not specified by the user, an unused internal IP
is assigned by the system.
Networks the instance will be connected to;
e.g., 'my-custom-network' or 'default'.
items:
type: object
additionalProperties: false
required:
- name
properties:
name:
type: string
description: |
Name of the network the instance will be connected to;
e.g., 'my-custom-network' or 'default'.
hasExternalIp:
$ref: '#/definitions/hasExternalIp'
natIP:
$ref: '#/definitions/natIP'
subnetwork:
$ref: '#/definitions/subnetwork'
networkIP:
$ref: '#/definitions/networkIP'
zone:
type: string
description: Availability zone. E.g. 'us-central1-a'
tags:
type: object
description: |
Expand All @@ -95,6 +156,7 @@ properties:
See https://cloud.google.com/compute/docs/machine-types for details.
canIpForward:
type: boolean
default: False
description: |
If "True". allows the instance to send and receive packets with non-matching destination
and source IPs.
Expand All @@ -107,6 +169,7 @@ properties:
- local-ssd
diskImage:
type: string
default: None
description: |
The source image for the disk. To create the disk with one of the
public operating system images, specify the image by its family name.
Expand Down Expand Up @@ -134,6 +197,7 @@ properties:
description: A collection of metadata key-value pairs.
items:
type: object
additionalProperties: false
properties:
key:
type: string
Expand All @@ -146,6 +210,7 @@ properties:
this instance. Only one service account per VM instance is supported.
items:
type: object
additionalProperties: false
properties:
email:
type: string
Expand All @@ -162,12 +227,19 @@ properties:

outputs:
properties:
- externalIp:
type: string
description: Reference to the external ip address of the new instance
- internalIp:
type: string
description: Reference to tbe internal ip address of the new instance
- networkInterfaces:
type: array
description: |
A list of network interfaces of the new instance.
items:
type: object
properties:
externalIp:
type: string
description: Reference to the external ip address of the new instance
internalIp:
type: string
description: Reference to tbe internal ip address of the new instance
- name:
type: string
description: A name of the instance resource
Expand All @@ -180,4 +252,3 @@ documentation:

examples:
- templates/instance/examples/instance.yaml

0 comments on commit fc452a8

Please sign in to comment.