def get_state(ctx, **kwargs):

    ctx.logger.info("initializing {0} cloud driver"
                    .format(Provider.CLOUDSTACK))
    cloud_driver = get_cloud_driver(ctx)

    instance_id = ctx.runtime_properties['instance_id']
    networking_type = ctx.runtime_properties['networking_type']

    ctx.logger.info('getting node with ID {0}'.format(instance_id))
    node = get_node_by_id(ctx, cloud_driver, instance_id)
    if node is None:
        return False

    if networking_type == 'network':
        ctx.runtime_properties['ip'] = node.private_ips[0]
        #ctx.runtime_properties['ip_address'] = node.private_ips[0]
        ctx.logger.info('instance started successfully with IP {0}'
                        .format(ctx.runtime_properties['ip']))
        return True

    elif networking_type == 'security_group':
        ctx.runtime.properties['ip'] = node.public_ips[0]
        ctx.logger.info('instance started successfully with IP {0}'
                        .format(ctx.runtime_properties['ip']))
        return True

    else:
        ctx.runtime_properties['ip'] = node.private_ips[0]
        ctx.logger.info('Cannot determine networking type,'
                        ' using private_ip as {0} ip'
                        .format(ctx.runtime_properties['ip']))
        return True
def disconnect_floating_ip(ctx, **kwargs):

    cloud_driver = get_cloud_driver(ctx)
    node_id = ctx.runtime_properties['instance_id']
    node = get_node_by_id(ctx, cloud_driver, node_id)
    portmaps = get_portmaps_by_node_id(ctx, cloud_driver, node_id)

    for portmap in portmaps:

        try:
            cloud_driver.ex_delete_port_forwarding_rule(node=node, rule=portmap)
        except Exception as e:
            ctx.logger.warn('Port forward may not have been removed: '
                            '{0}'.format(str(e)))
        return False

    return True
def delete(ctx, **kwargs):

    ctx.logger.info("initializing {0} cloud driver"
                    .format(Provider.CLOUDSTACK))
    cloud_driver = get_cloud_driver(ctx)

    instance_id = ctx['instance_id']
    if instance_id is None:
        raise NameError('could not find node ID in runtime context: {0} '
                        .format(instance_id))

    ctx.logger.info('getting node with ID: {0} '.format(instance_id))
    node = get_node_by_id(ctx, cloud_driver, instance_id)
    if node is None:
        raise NameError('could not find node with ID: {0} '
                        .format(instance_id))

    ctx.logger.info('destroying vm with details: {0}'.format(node.name))
    cloud_driver.destroy_node(node)
def start(ctx, **kwargs):
    ctx.logger.info("initializing {0} cloud driver"
                    .format(Provider.CLOUDSTACK))
    cloud_driver = get_cloud_driver(ctx)

    instance_id = ctx.runtime_properties['instance_id']
    if instance_id is None:
        raise RuntimeError(
            'could not find node ID in runtime context: {0} '
            .format(instance_id))

    ctx.logger.info('getting node with ID: {0} '.format(instance_id))
    node = get_node_by_id(ctx, cloud_driver, instance_id)
    if node is None:
        raise RuntimeError('could not find node with ID {0}'
                           .format(instance_id))

    ctx.logger.info('starting node with details {0}'.format(node.name))
    cloud_driver.ex_start(node)
def connect_network(ctx, **kwargs):

    instance_id = ctx.runtime_properties['instance_id']
    network_id = ctx.related.runtime_properties['network_id']



    cloud_driver = get_cloud_driver(ctx)
    # nodes = cloud_driver.list_nodes(instance_id)

    # network = [net for net in cloud_driver.ex_list_networks() if
    #            net.id == network_id ][0]
    # instance = [node for node in cloud_driver.list_nodes() if
    #             node.id == instance_id][0]

    node = get_node_by_id(ctx, cloud_driver, instance_id)
    network = get_network_by_id(ctx, cloud_driver, network_id)

    ctx.logger.info('Checking if there is a nic for  '
                    'vm: {0} with id: {1} in network {2} with id: {3}'
                    .format(node.name, network.name, instance_id, network_id,))

    nic_exists = get_nic_by_node_and_network_id(ctx, cloud_driver, node,
                                                network_id)

    #ctx.logger.info('Adding a NIC to VM {0} in Network {1}'.format(
    # node.name, network.name))

    if nic_exists is not None:
        ctx.logger.info('No need to connect network {0}, '
                        'already connected to nic {1}'
                        .format(network.name, nic_exists.id))
        return False

    cloud_driver.ex_attach_nic_to_node(node=node, network=network)
    #ctx.runtime_properties['nic_id'] = result.id

    return True
def disconnect_network(ctx, **kwargs):

    instance_id = ctx.runtime_properties['instance_id']
    network_id = ctx.related.runtime_properties['network_id']

    ctx.logger.info('Removing a NIC from VM-ID {0} in Network-ID {1}'.
                    format(instance_id, network_id))

    cloud_driver = get_cloud_driver(ctx)

    node = get_node_by_id(ctx, cloud_driver, instance_id)
    nic = get_nic_by_node_and_network_id(ctx, cloud_driver, node, network_id)

    #ctx.logger.info('Adding a NIC to VM {0} in Network with id {1}'.
    # format(node.name, nic.network_id))

    try:
        cloud_driver.ex_detach_nic_from_node(nic=nic, node=node)
    except Exception as e:
        ctx.logger.warn('NIC may not have been removed: {0}'.format(str(e)))
        return False

    return True
def connect_floating_ip(ctx, **kwargs):

    cloud_driver = get_cloud_driver(ctx)
    #server_config = _get_server_from_context(ctx)

    ctx.logger.debug('reading portmap configuration.')
    portmaps = ctx.properties['portmaps']

    if not portmaps:
        raise NonRecoverableError('Relation defined but no portmaps set'
                                  ' either remove relation or'
                                  ' define the portmaps')

    server_id = ctx.runtime_properties['instance_id']
    floating_ip_id = ctx.related.runtime_properties['external_id']
#    floating_ip_address = ctx.related.runtime_properties['floating_ip_address']

    for portmap in portmaps:

        protocol = portmap.get(['protocol'][0], None)
        pub_port = portmap.get(['public_port'][0], None)
        pub_end_port = portmap.get(['public_end_port'][0], None)
        priv_port = portmap.get(['private_port'][0], None)
        priv_end_port = portmap.get(['private_end_port'][0], None)

        #If not specified assume closed
        open_fw = portmap.get(['open_firewall'][0], False)

        if pub_port is None:
            raise NonRecoverableError('Please specify the public_port')
        elif pub_end_port is None:
            pub_end_port = pub_port

        if priv_port is None:
            raise NonRecoverableError('Please specify the private_port')
        elif priv_end_port is None:
            priv_end_port = priv_port

        if protocol is None:
            raise NonRecoverableError('Please specify the protocol TCP or UDP')

        node = get_node_by_id(ctx, cloud_driver, server_id)
        public_ip = get_public_ip_by_id(ctx, cloud_driver, floating_ip_id)

        try:

            cloud_driver.ex_create_port_forwarding_rule(node=node,
                                                        address=public_ip,
                                                        protocol=protocol,
                                                        public_port=pub_port,
                                                        public_end_port=
                                                        pub_end_port,
                                                        private_port=priv_port,
                                                        private_end_port=
                                                        priv_end_port,
                                                        openfirewall=open_fw)
        except Exception as e:
            ctx.logger.warn('Port forward creation failed: '
                            '{0}'.format(str(e)))
            return False

    return True