'Make connection to storage nodes
Connects to the first working node that it finds in nodes iter and
sends over the request headers. Returns a Putter to handle the rest of
the streaming, or None if no working nodes were found.
:param nodes: an iterator of the target storage nodes
:param part: ring partition number
:param req: a swob Request
:param headers: request headers
:param logger_thread_locals: The thread local values to be set on the
self.app.logger to retain transaction
logging information.
:return: an instance of a Putter'

def _connect_put_node(self, nodes, part, req, headers, logger_thread_locals):

    self.app.logger.thread_locals = logger_thread_locals
    for node in nodes:
        try:
            putter = self._make_putter(node, part, req, headers)
            self.app.set_node_timing(node, putter.connect_duration)
            return putter
        except InsufficientStorage:
            self.app.error_limit(node, _('ERROR    Insufficient    Storage'))
        except PutterConnectError as e:
            self.app.error_occurred(node, (_('ERROR    %(status)d    Expect:    100-continue    From    Object    Server') % {'status': e.status}))
        except (Exception, Timeout):
            self.app.exception_occurred(node, _('Object'), (_('Expect:    100-continue    on    %s') % req.swift_entity_path))
