Prepare the variables that are exposed to the servers.

        Most attributes in the server config are used directly.  However, due
        to variations in how cloud providers treat regions and availability
        zones, this method allows either the ``availability_zone`` or the
        ``region_name`` to be used as the target availability zone for a
        server.  If both are specified, then ``availability_zone`` is used.  If
        ``availability_zone`` is not specified in the server config, then the
        ``region_name`` value is used as the target availability zone.

def _prepare_servers(self):
        """
        Prepare the variables that are exposed to the servers.

        Most attributes in the server config are used directly.  However, due
        to variations in how cloud providers treat regions and availability
        zones, this method allows either the ``availability_zone`` or the
        ``region_name`` to be used as the target availability zone for a
        server.  If both are specified, then ``availability_zone`` is used.  If
        ``availability_zone`` is not specified in the server config, then the
        ``region_name`` value is used as the target availability zone.

        """
        stack = {
                A.NAME: self[A.NAME],
                A.VERSION: self[A.VERSION],
                }
        for server in self.get(R.SERVERS, []):
            # default cloud values
            if A.PROVIDER in server:
                if A.server.LAUNCH_TIMEOUT not in server:
                    server[A.server.LAUNCH_TIMEOUT] = DEFAULT_LAUNCH_TIMEOUT_S
                if A.server.POST_DELAY not in server:
                    server[A.server.POST_DELAY] = DEFAULT_LAUNCH_TIMEOUT_S
                if A.server.AZ not in server:
                    server[A.server.AZ] = server[A.server.REGION]

            # distribute the config scope attributes
            svars = {
                    A.STACK: stack,
                    A.SERVER_CLASS: server[A.NAME],
                    }
            for scope in server.get(A.server.SCOPES, []):
                # allow scopes to be defined inline
                if isinstance(scope, collections.Mapping):
                    svars.update(scope)
                else:
                    svars[scope] = self[scope]

            # make all of the launch-time attributes (e.g. disk_image_id,
            # launch_timeout_s, ssh_key_name, etc...) available as facts in
            # case you need them in a playbook.
            sattrs = server.copy()
            sattrs.pop(A.server.SCOPES, None)
            svars[A.server.BANG_ATTRS] = sattrs

            server[A.server.VARS] = svars