Hello, 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.
The change was introduced in: commit 21f60b155e4b65396ebf77e05a0ef300e7c3c1cf Author: Steve Baker <[email protected]> Change: https://review.openstack.org/#/c/67621/ 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: def handle_create(self): props = dict(self.properties) props[self.NAME] = self.physical_resource_name() sc = self.heat().software_configs.create(**props) ## HERE THE HEAT CLIENT IS CREATING A NEW SOFTWARE_CONFIG TO MAKE EACH ONE IMMUTABLE self.resource_id_set(sc.id) My concerns with this approach: 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, ..): curl -i -X POST -H 'X-Auth-Key: password' -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'X-Auth-Url: http://[host]:5000/v2.0' -H 'X-Auth-User: admin' -H 'User-Agent: python-heatclient' -d '{...}' http://10.0.2.15:8004/v1/{tenant_id} In this mode, the heat config file indicates standalone mode and can also indicate multicloud support: # /etc/heat/heat.conf [paste_deploy] flavor = standalone [auth_password] allowed_auth_uris = http://[host1]:5000/v2.0,http://[host2]:5000/v2.0 multi_cloud = true Any keystone URL which is referenced is unaware of the orchestration engine which is interacting with it. Herein lies the design flaw. When software_config calls self.heat(), it resolves clients.py's heat client: def heat(self): if self._heat: return self._heat con = self.context if self.auth_token is None: logger.error(_("Heat connection failed, no auth_token!")) return None # try the token args = { 'auth_url': con.auth_url, 'token': self.auth_token, 'username': None, 'password': None, 'ca_file': self._get_client_option('heat', 'ca_file'), 'cert_file': self._get_client_option('heat', 'cert_file'), 'key_file': self._get_client_option('heat', 'key_file'), 'insecure': self._get_client_option('heat', 'insecure') } endpoint_type = self._get_client_option('heat', 'endpoint_type') endpoint = self._get_heat_url() if not endpoint: endpoint = self.url_for(service_type='orchestration', endpoint_type=endpoint_type) self._heat = heatclient.Client('1', endpoint, **args) return self._heat 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. 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. One workaround that I've implemented locally is to change the logic to check for standalone mode and send the username and password. flavor = 'default' try: logger.info("Configuration is %s" % str(cfg.CONF)) flavor = cfg.CONF.paste_deploy.flavor except cfg.NoSuchOptError as nsoe: flavor = 'default' logger.info("Flavor is %s" % flavor) # We really should examine the pipeline to determine whether we're using authtoken or authpassword. if flavor == 'standalone': context_map = self.context.to_dict() if 'username' in context_map.keys(): username = context_map['username'] else: username = None if 'password' in context_map.keys(): password = context_map['password'] else: password = None logger.info("Configuring username='%s' and password='%s'" % (username, password)) args = { 'auth_url': con.auth_url, 'token': None, 'username': username, 'password': password, 'ca_file': self._get_client_option('heat', 'ca_file'), 'cert_file': self._get_client_option('heat', 'cert_file'), 'key_file': self._get_client_option('heat', 'key_file'), 'insecure': self._get_client_option('heat', 'insecure') } else: if self.auth_token is None: logger.error(_("Heat connection failed, no auth_token!")) return None ... Is this a known issue? -M ________________________________ Kind Regards, Michael D. Elder STSM | Master Inventor [email protected] | linkedin.com/in/mdelder "Success is not delivering a feature; success is learning how to solve the customer’s problem.” -Mark Cook
_______________________________________________ OpenStack-dev mailing list [email protected] http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
