'Return a Node object based on its ID.
:param  node_id: The id of the node
:type   node_id: ``str``
:keyword    project: Limit node returned to those configured under
the defined project.
:type       project: :class:`.CloudStackProject`
:rtype: :class:`CloudStackNode`'

def ex_get_node(self, node_id, project=None):

    list_nodes_args = {'id': node_id}
    list_ips_args = {}
    if project:
        list_nodes_args['projectid'] = project.id
        list_ips_args['projectid'] = project.id
    vms = self._sync_request('listVirtualMachines', params=list_nodes_args)
    if (not vms):
        raise Exception(("Node    '%s'    not    found" % node_id))
    vm = vms['virtualmachine'][0]
    addrs = self._sync_request('listPublicIpAddresses', params=list_ips_args)
    public_ips = {}
    for addr in addrs.get('publicipaddress', []):
        if ('virtualmachineid' not in addr):
            continue
        public_ips[addr['ipaddress']] = addr['id']
    node = self._to_node(data=vm, public_ips=list(public_ips.keys()))
    addresses = [CloudStackAddress(id=address_id, address=address, driver=node.driver) for (address, address_id) in public_ips.items()]
    node.extra['ip_addresses'] = addresses
    rules = []
    list_fw_rules = {'virtualmachineid': node_id}
    for addr in addresses:
        result = self._sync_request('listIpForwardingRules', params=list_fw_rules)
        for r in result.get('ipforwardingrule', []):
            if (str(r['virtualmachineid']) == node.id):
                rule = CloudStackIPForwardingRule(node, r['id'], addr, r['protocol'].upper(), r['startport'], r['endport'])
                rules.append(rule)
    node.extra['ip_forwarding_rules'] = rules
    rules = []
    public_ips = self.ex_list_public_ips()
    result = self._sync_request('listPortForwardingRules', params=list_fw_rules)
    for r in result.get('portforwardingrule', []):
        if (str(r['virtualmachineid']) == node.id):
            addr = [a for a in public_ips if (a.address == r['ipaddress'])]
            rule = CloudStackPortForwardingRule(node, r['id'], addr[0], r['protocol'].upper(), r['publicport'], r['privateport'], r['publicendport'], r['privateendport'])
            if (not (addr[0].address in node.public_ips)):
                node.public_ips.append(addr[0].address)
            rules.append(rule)
    node.extra['port_forwarding_rules'] = rules
    return node
