The API should only expose node UUIDs. The Port node_uuid is declared in such a way that it doesn't validate that a UUID is passed. It calls dbapi.get_node() (or the object version if another patch lands) which allows both ID and UUID lookups.
It also appears the tests are somehow relying on this. The JSON passed in the tests is correct, however internally the DB object is created and ends up being passed to Port().. The port code ends up taking the node_id from the DB and sets it as Port.node_uuid as can be seen in the traceback below:
File "ironic/tests/api/v1/test_ports.py", line 368, in test_create_port
response = self.post_json('/ports', pdict)
File "ironic/tests/api/base.py", line 134, in post_json
status=status, method="post")
File "ironic/tests/api/base.py", line 95, in _request_json
expect_errors=expect_errors
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/webtest/utils.py", line 41, in wrapper
return self._gen_request(method, url, **kw)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/webtest/app.py", line 626, in _gen_request
expect_errors=expect_errors)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/webtest/app.py", line 495, in do_request
res = req.get_response(app, catch_exc_info=True)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/webob/request.py", line 1316, in send
application, catch_exc_info=True)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/webob/request.py", line 1284, in call_application
app_iter = application(self.environ, start_response)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/webtest/lint.py", line 198, in lint_app
iterator = application(environ, start_response_wrapper)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/pecan/middleware/recursive.py", line 56, in __call__
return self.application(environ, start_response)
File "ironic/api/middleware/parsable_error.py", line 68, in __call__
app_iter = self.app(environ, replacement_start_response)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/pecan/core.py", line 570, in __call__
self.handle_request(req, resp)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/pecan/core.py", line 508, in handle_request
result = controller(*args, **kwargs)
File "/home/cbehrens/git/ironic/os.git/.tox/py27/local/lib/python2.7/site-packages/wsmeext/pecan.py", line 77, in callfunction
result = f(self, *args, **kwargs)
File "ironic/api/controllers/v1/port.py", line 254, in post
return Port.convert_with_links(new_port)
File "ironic/api/controllers/v1/port.py", line 99, in convert_with_links
port = Port(**rpc_port.as_dict())
File "ironic/api/controllers/v1/port.py", line 95, in __init__
setattr(self, 'node_uuid', kwargs.get('node_id'))
1:07 PM <jroll> BadCub: lol, I picked that up at the end of kilo and never finished it, I know Haomeng was working on the same thing but maybe fined a different bug?
1:09 PM <BadCub> Haomeng: are you working on something similar to/or dup of ^^^
1:10 PM <BadCub> thanks jroll :-) I will wait to hear from Haomeng on that one