<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 04/04/14 14:26, Michael Elder wrote:<br>
</div>
<blockquote
cite="mid:OF0BB3C63D.E901237B-ON85257CB0.0005FFCF-85257CB0.0007E21D@us.ibm.com"
type="cite"><font face="Arial" size="2">Hello,</font>
<br>
<br>
<font face="Arial" size="2">While adopting the latest from the
software
configurations in Icehouse, we discovered an issue with the new
software
configuration type and its assumptions about using the heat
client to perform
behavior. </font>
<br>
<br>
<font face="Arial" size="2">The change was introduced in:</font>
<br>
<br>
<font face="Arial" size="2">commit
21f60b155e4b65396ebf77e05a0ef300e7c3c1cf</font>
<br>
<font face="Arial" size="2">Author: Steve Baker
<a class="moz-txt-link-rfc2396E" href="mailto:sbaker@redhat.com"><sbaker@redhat.com></a></font>
<br>
<font face="Arial" size="2">Change: </font><a
moz-do-not-send="true"
href="https://review.openstack.org/#/c/67621/"><font
face="Arial" size="2">https://review.openstack.org/#/c/67621/</font></a>
<br>
<br>
<font face="Arial" size="2">The net is that the software config
type
in software_config.py lines 147-152 relies on the heat client to
create/clone
software configuration resources in the heat database:</font>
<br>
<br>
<font face="Arial" size="2"> def <b>handle_create</b>(<i>self</i>):</font>
<br>
<font face="Arial" size="2"> props = dict(<i>self</i>.properties)</font>
<br>
<font face="Arial" size="2"> props[<i>self</i>.NAME]
= <i>self</i>.physical_resource_name()</font>
<br>
<br>
<font face="Arial" size="2"> sc = <i>self</i>.heat().software_configs.create(**props)
##
HERE THE HEAT CLIENT IS CREATING A NEW SOFTWARE_CONFIG TO MAKE
EACH
ONE IMMUTABLE</font>
<br>
<font face="Arial" size="2"> <i>self</i>.resource_id_set(sc.id)</font>
<br>
<br>
<font face="Arial" size="2">My concerns with this approach:</font>
<br>
<br>
<font face="Arial" size="2">When used in standalone mode, the Heat
engine
receives headers which are used to drive authentication
(X-Auth-Url, X-Auth-User,
X-Auth-Key, ..):</font>
<br>
<br>
<font face="Arial" size="2">curl -i -X POST -H 'X-Auth-Key:
password'
-H 'Accept: application/json' -H 'Content-Type:
application/json' -H 'X-Auth-Url:
</font><a moz-do-not-send="true"
href="http://10.10.0.101:5000/v2.0%27"><font face="Arial"
size="2">http://[host]:5000/v2.0'</font></a><font face="Arial"
size="2">
-H 'X-Auth-User: admin' -H 'User-Agent: python-heatclient' -d
'{...}' </font><a moz-do-not-send="true"
href="http://10.0.2.15:8004/v1/"><font face="Arial" size="2">http://10.0.2.15:8004/v1/</font></a><font
face="Arial" size="2">{tenant_id}</font>
<br>
<br>
<font face="Arial" size="2">In this mode, the heat config file
indicates
standalone mode and can also indicate multicloud support:</font>
<br>
<br>
<font face="Arial" size="2"># /etc/heat/heat.conf</font>
<br>
<font face="Arial" size="2">[paste_deploy]</font>
<br>
<font face="Arial" size="2">flavor = standalone</font>
<br>
<br>
<font face="Arial" size="2">[auth_password]</font>
<br>
<font face="Arial" size="2">allowed_auth_uris =
http://[host1]:5000/v2.0,http://[host2]:5000/v2.0</font>
<br>
<font face="Arial" size="2">multi_cloud = true</font>
<br>
<br>
<font face="Arial" size="2">Any keystone URL which is referenced
is unaware
of the orchestration engine which is interacting with it. Herein
lies the
design flaw.</font>
<br>
</blockquote>
Its not so much a design flaw, its a bug where a new piece of code
interacts poorly with a mode that currently has few users and no
integration test coverage.<br>
<br>
<blockquote
cite="mid:OF0BB3C63D.E901237B-ON85257CB0.0005FFCF-85257CB0.0007E21D@us.ibm.com"
type="cite">
<br>
<font face="Arial" size="2">When software_config calls
self.heat(), it
resolves clients.py's heat client:</font>
<br>
<br>
<font face="Arial" size="2"> def <b>heat</b>(<i>self</i>):</font>
<br>
<font face="Arial" size="2"> if <i>self</i>._heat:</font>
<br>
<font face="Arial" size="2">
return <i>self</i>._heat</font>
<br>
<font face="Arial" size="2"> </font>
<br>
<font face="Arial" size="2"> con = <i>self</i>.context</font>
<br>
<font face="Arial" size="2"> if <i>self</i>.auth_token
is None:</font>
<br>
<font face="Arial" size="2">
logger.error(_(<i>"Heat connection failed, no auth_token!"</i>))</font>
<br>
<font face="Arial" size="2">
return None</font>
<br>
<font face="Arial" size="2"> # try the token</font>
<br>
<font face="Arial" size="2"> args = {</font>
<br>
<font face="Arial" size="2">
<i>'auth_url'</i>: con.auth_url,</font>
<br>
<font face="Arial" size="2">
<i>'token'</i>: <i>self</i>.auth_token,</font>
<br>
<font face="Arial" size="2">
<i>'<u>username</u>'</i>: None,</font>
<br>
<font face="Arial" size="2">
<i>'password'</i>: None,</font>
<br>
<font face="Arial" size="2">
<i>'ca_file'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'ca_file'</i>),</font>
<br>
<font face="Arial" size="2">
<i>'cert_file'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'cert_file'</i>),</font>
<br>
<font face="Arial" size="2">
<i>'key_file'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'key_file'</i>),</font>
<br>
<font face="Arial" size="2">
<i>'insecure'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'insecure'</i>) </font>
<br>
<font face="Arial" size="2"> }</font>
<br>
<br>
<font face="Arial" size="2"> endpoint_type
= <i>self</i>._get_client_option(<i>'heat'</i>, <i>'endpoint_type'</i>)</font>
<br>
<font face="Arial" size="2"> endpoint = <i>self</i>._get_heat_url()</font>
<br>
<font face="Arial" size="2"> if not endpoint:</font>
<br>
<font face="Arial" size="2">
endpoint = <i>self</i>.url_for(service_type=<i>'<u>orchestration</u>'</i>,</font>
<br>
<font face="Arial" size="2">
endpoint_type=endpoint_type)</font>
<br>
<font face="Arial" size="2"> <i>self</i>._heat
= heatclient.Client(<i>'1'</i>, endpoint, **args)</font>
<br>
<br>
<font face="Arial" size="2"> return <i>self</i>._heat</font>
<br>
<br>
<font face="Arial" size="2">Here, an attempt to look up the
orchestration
URL (which is already executing in the context of the heat
engine) comes
up wrong because Keystone doesn't know about this remote
standalone Heat
engine. </font>
<br>
<br>
</blockquote>
If you look at self._get_heat_url() you'll see that the heat.conf
[clients_heat] url will be used for the heat endpoint if it is set.
I would recommend setting that for standalone mode. A devstack
change for HEAT_STANDALONE would be helpful here.<br>
<br>
<blockquote
cite="mid:OF0BB3C63D.E901237B-ON85257CB0.0005FFCF-85257CB0.0007E21D@us.ibm.com"
type="cite"><font face="Arial" size="2">Further, at this point,
the username and
password are null, and when the auth_password standza is applied
in the
config file, Heat will deny any attempts at authorization which
only provide
a token. As I understand it today, that's because it doesn't
have individual
keystone admin users for all remote keystone services in the
list of allowed_auth_urls.
Hence, if only provided with a token, I don't think the heat
engine can
validate the token against the remote keystone. </font>
<br>
<br>
<font face="Arial" size="2">One workaround that I've implemented
locally
is to change the logic to check for standalone mode and send the
username
and password. </font>
<br>
<br>
<font face="Arial" size="2"> flavor = <i>'default'</i></font>
<br>
<font face="Arial" size="2"> try:</font>
<br>
<font face="Arial" size="2">
logger.info(<i>"Configuration is %s"</i> % str(cfg.CONF))</font>
<br>
<font face="Arial" size="2">
flavor = cfg.CONF.paste_deploy.flavor</font>
<br>
<font face="Arial" size="2"> except cfg.NoSuchOptError
as <u>nsoe</u>:</font>
<br>
<font face="Arial" size="2">
flavor = <i>'default'</i></font>
<br>
<font face="Arial" size="2"> logger.info(<i>"Flavor
is %s"</i> % flavor)</font>
<br>
<font face="Arial" size="2"> </font>
<br>
<font face="Arial" size="2"> # We really should
examine the pipeline to determine whether we're using <u>authtoken</u>
or <u>authpassword</u>.</font>
<br>
<font face="Arial" size="2"> if flavor ==
<i>'<u>standalone</u>'</i>:</font>
<br>
<font face="Arial" size="2">
</font>
<br>
<font face="Arial" size="2">
context_map = <i>self</i>.context.to_dict()</font>
<br>
<font face="Arial" size="2">
</font>
<br>
<font face="Arial" size="2">
if <i>'<u>username</u>'</i> in context_map.keys():</font>
<br>
<font face="Arial" size="2">
username = context_map[<i>'<u>username</u>'</i>]</font>
<br>
<font face="Arial" size="2">
else:</font>
<br>
<font face="Arial" size="2">
username = None</font>
<br>
<font face="Arial" size="2"> </font>
<br>
<font face="Arial" size="2">
if <i>'password'</i> in context_map.keys():</font>
<br>
<font face="Arial" size="2">
password = context_map[<i>'password'</i>]</font>
<br>
<font face="Arial" size="2">
else:</font>
<br>
<font face="Arial" size="2">
password = None</font>
<br>
<font face="Arial" size="2">
</font>
<br>
<font face="Arial" size="2">
logger.info(<i>"Configuring <u>username</u>='%s' and
password='%s'"</i>
% (username, password))</font>
<br>
<font face="Arial" size="2">
args = {</font>
<br>
<font face="Arial" size="2">
<i>'auth_url'</i>: con.auth_url,</font>
<br>
<font face="Arial" size="2">
<i>'token'</i>: None,</font>
<br>
<font face="Arial" size="2">
<i>'<u>username</u>'</i>: username,</font>
<br>
<font face="Arial" size="2">
<i>'password'</i>: password,</font>
<br>
<font face="Arial" size="2">
<i>'ca_file'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'ca_file'</i>),</font>
<br>
<font face="Arial" size="2">
<i>'cert_file'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'cert_file'</i>),</font>
<br>
<font face="Arial" size="2">
<i>'key_file'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'key_file'</i>),</font>
<br>
<font face="Arial" size="2">
<i>'insecure'</i>: <i>self</i>._get_client_option(<i>'heat'</i>,
<i>'insecure'</i>)</font>
<br>
<font face="Arial" size="2">
} </font>
<br>
<font face="Arial" size="2"> else:</font>
<br>
<font face="Arial" size="2">
if <i>self</i>.auth_token is None:</font>
<br>
<font face="Arial" size="2">
logger.error(_(<i>"Heat connection failed, no auth_token!"</i>))</font>
<br>
<font face="Arial" size="2">
return None</font>
<br>
<font face="Arial" size="2">...</font>
<br>
<br>
<font face="Arial" size="2">Is this a known issue? </font>
<br>
</blockquote>
This is a great summary of the problem, but it really belongs in a
launchpad bug. Lets discuss potential solutions there.<br>
<br>
<a class="moz-txt-link-freetext" href="https://bugs.launchpad.net/heat/+filebug">https://bugs.launchpad.net/heat/+filebug</a><br>
<br>
cheers<br>
</body>
</html>