# Buggy code
def create(vm_):
    """
    Create a single VM from a data dict
    """
    try:
        # Check for required profile parameters before sending any API calls.
        if (
            vm_["profile"]
            and config.is_profile_configured(
                __opts__,
                __active_provider_name__ or "openstack",
                vm_["profile"],
                vm_=vm_,
            )
            is False
        ):
            return False
    except AttributeError:
        pass

    # Since using "provider: <provider-engine>" is deprecated, alias provider
    # to use driver: "driver: <provider-engine>"
    if "provider" in vm_:
        vm_["driver"] = vm_.pop("provider")

    deploy = config.get_cloud_config_value("deploy", vm_, __opts__)
    key_filename = config.get_cloud_config_value(
        "ssh_key_file", vm_, __opts__, search_global=False, default=None
    )
    if key_filename is not None:
        key_filename = os.path.expanduser(key_filename)
        if not os.path.isfile(key_filename):
            raise SaltCloudConfigError(
                "The defined ssh_key_file '{0}' does not exist".format(key_filename)
            )

    vm_["key_filename"] = key_filename

    __utils__["cloud.fire_event"](
        "event",
        "starting create",
        "salt/cloud/{0}/creating".format(vm_["name"]),
        {
            "name": vm_["name"],
            "profile": vm_["profile"],
            "provider": vm_["driver"],
        },
        transport=__opts__["transport"],
    )

    conn = get_conn()

    if "instance_id" in vm_:
        # This was probably created via another process, and doesn't have
        # things like salt keys created yet, so let's create them now.
        if "pub_key" not in vm_ and "priv_key" not in vm_:
            log.debug("Generating minion keys for '{0[name]}'".format(vm_))
            vm_["priv_key"], vm_["pub_key"] = salt.utils.cloud.gen_keys(
                salt.config.get_cloud_config_value("keysize", vm_, __opts__)
            )
        data = conn.ex_get_node_details(vm_["instance_id"])
        if (
            vm_["key_filename"] is None
            and "change_password" in __opts__
            and __opts__["change_password"] is True
        ):
            vm_["password"] = sup.secure_password()
            conn.ex_set_password(data, vm_["password"])
        networks(vm_)
    else:
        # Put together all of the information required to request the instance,
        # and then fire off the request for it
        data, vm_ = request_instance(vm_)

        # Pull the instance ID, valid for both spot and normal instances
        vm_["instance_id"] = data.id

    def __query_node_data(vm_, data, floating):
        try:
            node = show_instance(vm_["name"], "action")
            log.debug(
                "Loaded node data for {0}:\n{1}".format(
                    vm_["name"], pprint.pformat(node)
                )
            )
        except Exception as err:
            log.error(
                "Failed to get nodes list: {0}".format(err),
                # Show the traceback if the debug logging level is enabled
                exc_info_on_loglevel=logging.DEBUG,
            )
            # Trigger a failure in the wait for IP function
            return False

        running = node["state"] == NodeState.RUNNING
        if not running:
            # Still not running, trigger another iteration
            return

        if rackconnect(vm_) is True:
            check_libcloud_version((0, 14, 0), why="rackconnect: True")
            extra = node.get("extra")
            rc_status = extra.get("metadata", {}).get(
                "rackconnect_automation_status", ""
            )
            access_ip = extra.get("access_ip", "")

            if rc_status != "DEPLOYED":
                log.debug("Waiting for Rackconnect automation to complete")
                return

        if managedcloud(vm_) is True:
            extra = node.get("extra")
            mc_status = extra.get("metadata", {}).get(
                "rax_service_level_automation", ""
            )

            if mc_status != "Complete":
                log.debug("Waiting for managed cloud automation to complete")
                return

        public = node["public_ips"]
        if floating:
            try:
                name = data.name
                ip = floating[0].ip_address
                conn.ex_attach_floating_ip_to_node(data, ip)
                log.info("Attaching floating IP '{0}' to node '{1}'".format(ip, name))
                data.public_ips.append(ip)
                public = data.public_ips
            except Exception:
                # Note(pabelanger): Because we loop, we only want to attach the
                # floating IP address one. So, expect failures if the IP is
                # already attached.
                pass

        result = []
        private = node["private_ips"]
        if private and not public:
            log.warn(
                "Private IPs returned, but not public... Checking for misidentified IPs"
            )
            for private_ip in private:
                private_ip = preferred_ip(vm_, [private_ip])
                if salt.utils.cloud.is_public_ip(private_ip):
                    log.warn("{0} is a public IP".format(private_ip))
                    data.public_ips.append(private_ip)
                    log.warn(
                        "Public IP address was not ready when we last checked."
                        " Appending public IP address now."
                    )
                    public = data.public_ips
                else:
                    log.warn("{0} is a private IP".format(private_ip))
                    ignore_ip = ignore_cidr(vm_, private_ip)
                    if private_ip not in data.private_ips and not ignore_ip:
                        result.append(private_ip)

        if rackconnect(vm_) is True and ssh_interface(vm_) != "private_ips":
            data.public_ips = access_ip
            return data

        # populate return data with private_ips
        # when ssh_interface is set to private_ips and public_ips exist
        if not result and ssh_interface(vm_) == "private_ips":
            for private_ip in private:
                ignore_ip = ignore_cidr(vm_, private_ip)
                if private_ip not in data.private_ips and not ignore_ip:
                    result.append(private_ip)

        if result:
            log.debug("result = {0}".format(result))
            data.private_ips = result
            if ssh_interface(vm_) == "private_ips":
                return data

        if public:
            data.public_ips = public
            if ssh_interface(vm_) != "private_ips":
                return data

    try:
        data = salt.utils.cloud.wait_for_ip(
            __query_node_data,
            update_args=(vm_, data, vm_["floating"]),
            timeout=config.get_cloud_config_value(
                "wait_for_ip_timeout", vm_, __opts__, default=10 * 60
            ),
            interval=config.get_cloud_config_value(
                "wait_for_ip_interval", vm_, __opts__, default=10
            ),
        )
    except (SaltCloudExecutionTimeout, SaltCloudExecutionFailure) as exc:
        try:
            # It might be already up, let's destroy it!
            destroy(vm_["name"])
        except SaltCloudSystemExit:
            pass
        finally:
            raise SaltCloudSystemExit(str(exc))

    log.debug("VM is now running")

    if ssh_interface(vm_) == "private_ips":
        ip_address = preferred_ip(vm_, data.private_ips)
    elif rackconnect(vm_) is True and ssh_interface(vm_) != "private_ips":
        ip_address = data.public_ips
    else:
        ip_address = preferred_ip(vm_, data.public_ips)
    log.debug("Using IP address {0}".format(ip_address))

    if salt.utils.cloud.get_salt_interface(vm_, __opts__) == "private_ips":
        salt_ip_address = preferred_ip(vm_, data.private_ips)
        log.info("Salt interface set to: {0}".format(salt_ip_address))
    else:
        salt_ip_address = preferred_ip(vm_, data.public_ips)
        log.debug("Salt interface set to: {0}".format(salt_ip_address))

    if not ip_address:
        raise SaltCloudSystemExit("A valid IP address was not found")

    vm_["salt_host"] = salt_ip_address
    vm_["ssh_host"] = ip_address
    ret = __utils__["cloud.bootstrap"](vm_, __opts__)
    ret.update(data.__dict__)

    if hasattr(data, "extra") and "password" in data.extra:
        del data.extra["password"]

    log.info("Created Cloud VM '{0[name]}'".format(vm_))
    log.debug(
        "'{0[name]}' VM creation details:\n{1}".format(
            vm_, pprint.pformat(data.__dict__)
        )
    )

    __utils__["cloud.fire_event"](
        "event",
        "created instance",
        "salt/cloud/{0}/created".format(vm_["name"]),
        {
            "name": vm_["name"],
            "profile": vm_["profile"],
            "provider": vm_["driver"],
        },
        transport=__opts__["transport"],
    )

    return ret


# Traceback (TypeError)
'private_ips': ['an:ip:v6', 'an.ip.v4'],
'public_ips': [],
'size': None,
'state': 0}
[WARNING ] Private IPs returned, but not public... Checking for misidentified IPs
[ERROR   ] There was a profile error: argument of type 'bool' is not iterable
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/salt/cloud/cli.py", line 284, in run
self.config.get('names')
File "/usr/lib/python2.7/dist-packages/salt/cloud/__init__.py", line 1458, in run_profile
ret[name] = self.create(vm_)
File "/usr/lib/python2.7/dist-packages/salt/cloud/__init__.py", line 1288, in create
output = self.clouds[func](vm_)
File "/usr/lib/python2.7/dist-packages/salt/cloud/clouds/openstack.py", line 774, in create
'wait_for_ip_interval', vm_, __opts__, default=10),
File "/usr/lib/python2.7/dist-packages/salt/utils/cloud.py", line 2371, in wait_for_ip
data = update_callback(*update_args, **update_kwargs)
File "/usr/lib/python2.7/dist-packages/salt/cloud/clouds/openstack.py", line 730, in __query_node_data
if salt.utils.cloud.is_public_ip(private_ip):
File "/usr/lib/python2.7/dist-packages/salt/utils/cloud.py", line 2266, in is_public_ip
if ':' in ip:
TypeError: argument of type 'bool' is not iterable

# Fixed code
def create(vm_):
    """
    Create a single VM from a data dict
    """
    try:
        # Check for required profile parameters before sending any API calls.
        if (
            vm_["profile"]
            and config.is_profile_configured(
                __opts__,
                __active_provider_name__ or "openstack",
                vm_["profile"],
                vm_=vm_,
            )
            is False
        ):
            return False
    except AttributeError:
        pass

    # Since using "provider: <provider-engine>" is deprecated, alias provider
    # to use driver: "driver: <provider-engine>"
    if "provider" in vm_:
        vm_["driver"] = vm_.pop("provider")

    deploy = config.get_cloud_config_value("deploy", vm_, __opts__)
    key_filename = config.get_cloud_config_value(
        "ssh_key_file", vm_, __opts__, search_global=False, default=None
    )
    if key_filename is not None:
        key_filename = os.path.expanduser(key_filename)
        if not os.path.isfile(key_filename):
            raise SaltCloudConfigError(
                "The defined ssh_key_file '{0}' does not exist".format(key_filename)
            )

    vm_["key_filename"] = key_filename

    __utils__["cloud.fire_event"](
        "event",
        "starting create",
        "salt/cloud/{0}/creating".format(vm_["name"]),
        {
            "name": vm_["name"],
            "profile": vm_["profile"],
            "provider": vm_["driver"],
        },
        transport=__opts__["transport"],
    )

    conn = get_conn()

    if "instance_id" in vm_:
        # This was probably created via another process, and doesn't have
        # things like salt keys created yet, so let's create them now.
        if "pub_key" not in vm_ and "priv_key" not in vm_:
            log.debug("Generating minion keys for '{0[name]}'".format(vm_))
            vm_["priv_key"], vm_["pub_key"] = salt.utils.cloud.gen_keys(
                salt.config.get_cloud_config_value("keysize", vm_, __opts__)
            )
        data = conn.ex_get_node_details(vm_["instance_id"])
        if (
            vm_["key_filename"] is None
            and "change_password" in __opts__
            and __opts__["change_password"] is True
        ):
            vm_["password"] = sup.secure_password()
            conn.ex_set_password(data, vm_["password"])
        networks(vm_)
    else:
        # Put together all of the information required to request the instance,
        # and then fire off the request for it
        data, vm_ = request_instance(vm_)

        # Pull the instance ID, valid for both spot and normal instances
        vm_["instance_id"] = data.id

    def __query_node_data(vm_, data, floating):
        try:
            node = show_instance(vm_["name"], "action")
            log.debug(
                "Loaded node data for {0}:\n{1}".format(
                    vm_["name"], pprint.pformat(node)
                )
            )
        except Exception as err:
            log.error(
                "Failed to get nodes list: {0}".format(err),
                # Show the traceback if the debug logging level is enabled
                exc_info_on_loglevel=logging.DEBUG,
            )
            # Trigger a failure in the wait for IP function
            return False

        running = node["state"] == NodeState.RUNNING
        if not running:
            # Still not running, trigger another iteration
            return

        if rackconnect(vm_) is True:
            check_libcloud_version((0, 14, 0), why="rackconnect: True")
            extra = node.get("extra")
            rc_status = extra.get("metadata", {}).get(
                "rackconnect_automation_status", ""
            )
            access_ip = extra.get("access_ip", "")

            if rc_status != "DEPLOYED":
                log.debug("Waiting for Rackconnect automation to complete")
                return

        if managedcloud(vm_) is True:
            extra = node.get("extra")
            mc_status = extra.get("metadata", {}).get(
                "rax_service_level_automation", ""
            )

            if mc_status != "Complete":
                log.debug("Waiting for managed cloud automation to complete")
                return

        public = node["public_ips"]
        if floating:
            try:
                name = data.name
                ip = floating[0].ip_address
                conn.ex_attach_floating_ip_to_node(data, ip)
                log.info("Attaching floating IP '{0}' to node '{1}'".format(ip, name))
                data.public_ips.append(ip)
                public = data.public_ips
            except Exception:
                # Note(pabelanger): Because we loop, we only want to attach the
                # floating IP address one. So, expect failures if the IP is
                # already attached.
                pass

        result = []
        private = node["private_ips"]
        if private and not public:
            log.warn(
                "Private IPs returned, but not public... Checking for misidentified IPs"
            )
            for private_ip in private:
                private_ip = preferred_ip(vm_, [private_ip])
                if private_ip is False:
                    continue
                if salt.utils.cloud.is_public_ip(private_ip):
                    log.warn("{0} is a public IP".format(private_ip))
                    data.public_ips.append(private_ip)
                    log.warn(
                        "Public IP address was not ready when we last checked."
                        " Appending public IP address now."
                    )
                    public = data.public_ips
                else:
                    log.warn("{0} is a private IP".format(private_ip))
                    ignore_ip = ignore_cidr(vm_, private_ip)
                    if private_ip not in data.private_ips and not ignore_ip:
                        result.append(private_ip)

        if rackconnect(vm_) is True and ssh_interface(vm_) != "private_ips":
            data.public_ips = access_ip
            return data

        # populate return data with private_ips
        # when ssh_interface is set to private_ips and public_ips exist
        if not result and ssh_interface(vm_) == "private_ips":
            for private_ip in private:
                ignore_ip = ignore_cidr(vm_, private_ip)
                if private_ip not in data.private_ips and not ignore_ip:
                    result.append(private_ip)

        if result:
            log.debug("result = {0}".format(result))
            data.private_ips = result
            if ssh_interface(vm_) == "private_ips":
                return data

        if public:
            data.public_ips = public
            if ssh_interface(vm_) != "private_ips":
                return data

    try:
        data = salt.utils.cloud.wait_for_ip(
            __query_node_data,
            update_args=(vm_, data, vm_["floating"]),
            timeout=config.get_cloud_config_value(
                "wait_for_ip_timeout", vm_, __opts__, default=10 * 60
            ),
            interval=config.get_cloud_config_value(
                "wait_for_ip_interval", vm_, __opts__, default=10
            ),
        )
    except (SaltCloudExecutionTimeout, SaltCloudExecutionFailure) as exc:
        try:
            # It might be already up, let's destroy it!
            destroy(vm_["name"])
        except SaltCloudSystemExit:
            pass
        finally:
            raise SaltCloudSystemExit(str(exc))

    log.debug("VM is now running")

    if ssh_interface(vm_) == "private_ips":
        ip_address = preferred_ip(vm_, data.private_ips)
    elif rackconnect(vm_) is True and ssh_interface(vm_) != "private_ips":
        ip_address = data.public_ips
    else:
        ip_address = preferred_ip(vm_, data.public_ips)
    log.debug("Using IP address {0}".format(ip_address))

    if salt.utils.cloud.get_salt_interface(vm_, __opts__) == "private_ips":
        salt_ip_address = preferred_ip(vm_, data.private_ips)
        log.info("Salt interface set to: {0}".format(salt_ip_address))
    else:
        salt_ip_address = preferred_ip(vm_, data.public_ips)
        log.debug("Salt interface set to: {0}".format(salt_ip_address))

    if not ip_address:
        raise SaltCloudSystemExit("A valid IP address was not found")

    vm_["salt_host"] = salt_ip_address
    vm_["ssh_host"] = ip_address
    ret = __utils__["cloud.bootstrap"](vm_, __opts__)
    ret.update(data.__dict__)

    if hasattr(data, "extra") and "password" in data.extra:
        del data.extra["password"]

    log.info("Created Cloud VM '{0[name]}'".format(vm_))
    log.debug(
        "'{0[name]}' VM creation details:\n{1}".format(
            vm_, pprint.pformat(data.__dict__)
        )
    )

    __utils__["cloud.fire_event"](
        "event",
        "created instance",
        "salt/cloud/{0}/created".format(vm_["name"]),
        {
            "name": vm_["name"],
            "profile": vm_["profile"],
            "provider": vm_["driver"],
        },
        transport=__opts__["transport"],
    )

    return ret