CloudVE / cloudbridge

A consistent interface to multiple IaaS clouds; in Python.
https://cloudbridge.cloudve.org
MIT License
114 stars 51 forks source link

Possibility to launch instances with public IPs #255

Open selshowk opened 3 years ago

selshowk commented 3 years ago

Assigning a public IP directly to an instance is simpler than using a floating IP (e.g. elastic IPs in AWS have stringent limits).

On AWS it seems like we can launch an instance with a public IP simply by setting a flag in thenetwork section of "create_instances" boto call. I'm not sure if GCP or Azure have similar flags but it would be useful to be able to pass in this flag either directly in the InstanceService.create() function or via a kwarg that's passed through by the AWS implementation (and maybe the others). This is done for e.g. the iam_instance_profile now. Is there a reason not to do this or would there be a better way to do it?

nuwang commented 3 years ago

@afgane @almahmoud Any thoughts on this issue?

selshowk commented 3 years ago

Here is a working minimal modification for the instance create function in AWS provider. In this case implementation I use a flag to determine whether to use a public IP but it could, in principle, be in the kwargs:

def create(self, label, image, vm_type, subnet,
           key_pair=None, vm_firewalls=None, user_data=None,
           launch_config=None, 
           associate_public_ip = False,
           **kwargs):
    AWSInstance.assert_valid_resource_label(label)
    image_id = image.id if isinstance(image, MachineImage) else image
    vm_size = vm_type.id if \
        isinstance(vm_type, VMType) else vm_type
    subnet = (self.provider.networking.subnets.get(subnet)
              if isinstance(subnet, str) else subnet)
    zone_name = self.provider.zone_name
    key_pair_name = key_pair.name if isinstance(
        key_pair,
        KeyPair) else key_pair
    if launch_config:
        bdm = self._process_block_device_mappings(launch_config)
    else:
        bdm = None

    subnet_id, zone_id, vm_firewall_ids = \
        self._resolve_launch_options(subnet, zone_name, vm_firewalls)

    placement = {'AvailabilityZone': zone_id} if zone_id else None
    network_interfaces = [{
            'DeviceIndex': 0,
            'SubnetId' : f"{subnet_id}",
            'Groups': vm_firewall_ids,
            'AssociatePublicIpAddress': True,
            'DeleteOnTermination': True,
        }] if associate_public_ip else None
    # if using a network interface we don't set subnet or groups
    if network_interfaces:
        vm_firewall_ids = None
        subnet_id = None
    inst = self.svc.create(
        'create_instances',
        ImageId=image_id,
        MinCount=1,
        MaxCount=1,
        KeyName=key_pair_name,
        SecurityGroupIds=vm_firewall_ids or None,
        UserData=str(user_data) or None,
        InstanceType=vm_size,
        Placement=placement,
        BlockDeviceMappings=bdm,
        SubnetId=subnet_id,
        IamInstanceProfile=kwargs.pop('iam_instance_profile', None),
        NetworkInterfaces=network_interfaces
    )
    if inst and len(inst) == 1:
        # Wait until the resource exists
        # pylint:disable=protected-access
        inst[0]._wait_till_exists()
        # Tag the instance w/ the name
        inst[0].label = label
        return inst[0]
    raise ValueError(
        'Expected a single object response, got a list: %s' % inst)

I've skimmed the azure implementation and I think a similar thing can be accomplished by setting a public ip in the nic_params as done e.g. here. Though from that link it seems the address might have to be created manually for azure.

nuwang commented 3 years ago

@selshowk I'm not sure we'll be able to introduce a top level parameter, since it probably won't be possible to make this work in a cloud-independent way. In the MS sample you sent for example, there's logic for manually creating a public ip. OpenStack's public ip assignment is network dependent, and the standard way is to use a floating ip.

We'd be happy to accept to a PR through kwargs for AWS though. (in the same way that iam_instance_profile is handled)

selshowk commented 3 years ago

Ok, I am currently implementing a multi-cloud solution using cloudbridge and will try to provide PRs for the above functionality as I figure out how/if its possible for each provider.

nuwang commented 3 years ago

@selshowk Is this still an issue?

selshowk commented 3 years ago

I haven't generated a PR yet and the functionality is not yet there so not sure. Feel free to keep/close it as you like.

nuwang commented 3 years ago

@selshowk No worries, take your time. I'll keep this open and we can include this in a patch release.