Custom Search
Showing posts with label OpenStack Heat. Show all posts
Showing posts with label OpenStack Heat. Show all posts

Wednesday, July 9, 2014

Howto Install OpenStack Heat standalone Using Puppet

Code: https://github.com/sajuptpm/openstack-puppet-scripts/tree/master/heat_standalone

1)
Install Latest Puppet


# wget https://apt.puppetlabs.com/puppetlabs-release-trusty.deb
# sudo dpkg -i puppetlabs-release-trusty.deb
# sudo sh -c 'echo "deb http://apt.puppetlabs.com// trusty main" >> /etc/apt/sources.list.d/puppet.list'

# sudo apt-get update

# sudo apt-get install puppet

# puppet --version

# dpkg -L puppet

2)
Create following directories

# sudo mkdir /var/puppet
# sudo mkdir /var/puppet/modules

3)
a)
* Install stable "puppet-heat"

https://github.com/stackforge/puppet-heat/blob/master/README.md
* Run "puppet man module" to get help

# sudo puppet module install --target-dir /var/puppet/modules puppetlabs/heat

b)
* Install unstable "puppet-heat"

https://github.com/stackforge/puppet-openstack#installing-latest-unstable-openstack-module-from-source

# cd /var/puppet/modules
# git clone https://github.com/stackforge/puppet-heat.git heat
# cd heat
# gem install librarian-puppet
# librarian-puppet install --path ../

4)
Create a directory to put your custom puppet files

# mkdir ~/puppet-test
# mkdir ~/puppet-test/manifests
# cd  ~/puppet-test/manifests

5)
Create a "site.pp" to put your puppet code

# cd  ~/puppet-test/manifests
# vim site.pp

class { '::heat':
    keystone_host => "192.168.56.102",
    keystone_port => "35357",
    keystone_user => "heat",
    keystone_tenant => "services",
    package_ensure => "latest",
  }

#https://github.com/stackforge/puppet-heat/blob/master/manifests/init.pp
#http://docs.openstack.org/trunk/config-reference/content/ch_configuring-openstack-orchestration.html

Notes:
* This will not install any heat services like "heat-engine".
* but, this will create the file "/etc/heat/heat.conf" and install "/usr/bin/heat" binary
* To install heat services, we need to invoke other calls, will explain later. see step:12.

6)
a)
* Check "README.md" of "puppet-heat" module

https://github.com/stackforge/puppet-heat/blob/master/README.md

b)
* Check the "init.pp" of "puppet-heat" module and understand the definition of class "heat" and what are the arguments we can pass and what are the default arguments.
https://github.com/stackforge/puppet-heat/blob/master/manifests/init.pp

7)
Run puppet and install heat

# sudo puppet apply  --verbose --modulepath /var/puppet/modules site.pp

You can also use --debug and --noop options


8)
Install "heat-engine".


a)
# cd  ~/puppet-test/manifests
# vim site.pp

class { '::heat':
    keystone_host => "192.168.56.102",
    keystone_port => "35357",
    keystone_user => "heat",
    keystone_tenant => "services",
    package_ensure => "latest",
    sql_connection => "sqlite:////var/lib/heat/sqlite_db",
  }

class { 'heat::engine':
        auth_encryption_key => "mykey123",
}

#https://github.com/stackforge/puppet-heat/blob/master/manifests/engine.pp
#http://docs.openstack.org/trunk/config-reference/content/ch_configuring-openstack-orchestration.html

b)
Run puppet and install heat-engine

# sudo puppet apply  --verbose --modulepath /var/puppet/modules site.pp

You can also use --debug and --noop options

c)
This will create following files


/usr/bin/heat-engine
/usr/bin/heat-keystone-setup
/usr/bin/heat-manage

/etc/init.d/heat-engine

/etc/init/heat-engine.conf

d)
Check following log files to debug


/var/log/heat/heat-engine.log
/var/log/heat/heat-manage.log

e)
Check

#dpkg -L heat-engine

9)
Install "heat-api".


a)
# cd  ~/puppet-test/manifests
# vim site.pp

class { '::heat':
    keystone_host => "192.168.56.1",
    keystone_port => "35357",
    keystone_user => "heat",
    keystone_tenant => "services",
    package_ensure => "latest",
    sql_connection => "sqlite:////var/lib/heat/sqlite_db",
  }

class { 'heat::engine':
        auth_encryption_key => "mykey123",
}

class { 'heat::api':
        bind_host => "127.0.0.1",
        bind_port => "8004",
}


#https://github.com/stackforge/puppet-heat/blob/master/manifests/api.pp
#http://docs.openstack.org/trunk/config-reference/content/orchestration-configuring-api.html

b)
Run puppet and install heat-api

# sudo puppet apply  --verbose --modulepath /var/puppet/modules site.pp

You can also use --debug and --noop options

c)
This will create following files


/usr/bin/heat-api

/etc/init.d/heat-api
/etc/init/heat-api.conf

d)
Check following log files to debug


/var/log/heat/heat-api.log

e)
Check

#dpkg -L heat-api

10)
Install rabbitmq


a)
* Install stable "rabbitmq"

https://github.com/puppetlabs/puppetlabs-rabbitmq/blob/master/README.md
https://forge.puppetlabs.com/puppetlabs/rabbitmq
* Run "puppet man module" to get help

# sudo puppet module install --target-dir /var/puppet/modules puppetlabs/rabbitmq

b)
# cd  ~/puppet-test/manifests
# vim site.pp

####Heat
class { '::heat':
    keystone_host => "192.168.56.1",
    keystone_port => "35357",
    keystone_user => "heat",
    keystone_tenant => "services",
    package_ensure => "latest",
    sql_connection => "sqlite:////var/lib/heat/sqlite_db",
  }


####Heat Engine
class { 'heat::engine':
        auth_encryption_key => "mykey123",
}

####Heat API
class { 'heat::api':
        bind_host => "127.0.0.1",
        bind_port => "8004",
}

####Rabbitmq
class { '::rabbitmq':
}

c)
Run puppet and install rabbitmq

# sudo puppet apply  --verbose --modulepath /var/puppet/modules site.pp

You can also use --debug and --noop options

d)
Check the status of rabbitmq-server

#sudo /etc/init.d/rabbitmq-server status

e)
Ensure that rabbitmq-server is running on port 5672

#sudo netstat -tuplen | grep :5672
#sudo netstat -tuplen | grep :5672 | awk '{ print $9 }'

f)
Ensure that "heat-engine" is working without any issue

#sudo tail -f /var/log/heat/heat-engine.log
#sudo service heat-engine restart

11)
Install "heat-cfn"


a)
What is heat-cfn or heat-cfntools ?


* heat-cfntools are tools required to be installed on Heat provisioned cloud instances (vms).
https://github.com/openstack/heat-cfntools <== IMP

* We an use heat-cfntools to install install packages, and starts services in side a VM with the help of "cfn-init" which Reads the AWS::CloudFormation::Init for the instance resource.

* We can use heat-cfntools to implement WaitCondition in VM with the help of "cfn-signal" which Waits for an application in the VM to be ready before continuing.

b)
# cd  ~/puppet-test/manifests
# vim site.pp

####Heat
class { '::heat':
    keystone_host => "192.168.56.1",
    keystone_port => "35357",
    keystone_user => "heat",
    keystone_tenant => "services",
    package_ensure => "latest",
    sql_connection => "sqlite:////var/lib/heat/sqlite_db",
  }

####Heat Engine
class { 'heat::engine':
        auth_encryption_key => "mykey123",
}

####Heat API
class { 'heat::api':
        bind_host => "127.0.0.1",
        bind_port => "8004",
}

####Rabbitmq
class { '::rabbitmq':
}

####Heat cfn
class { 'heat::api_cfn':
        bind_host => "127.0.0.1",
        bind_port => "8000",
}

#http://docs.openstack.org/trunk/config-reference/content/orchestration-configuring-api.html
#https://github.com/stackforge/puppet-heat/blob/master/manifests/api_cfn.pp

c)
Run puppet and install heat-cfn

# sudo puppet apply  --verbose --modulepath /var/puppet/modules site.pp

You can also use --debug and --noop options

d)
This will create following files


/etc/init.d/heat-api-cfn
/etc/init/heat-api-cfn.conf

/usr/bin/heat-api-cfn

e)
Check following log files to debug

/var/log/heat/heat-api-cfn.log

f)
Check

#dpkg -L heat-api-cfn

12)
How to Setup Standalone Heat

How to get Heat to work with a remote OpenStack

http://docs.openstack.org/developer/heat/getting_started/standalone.html

a)
Edit heat.conf
#sudo vim /etc/heat/heat.conf
flavor=standalone

b)
Restart heat-engine and heat-api

#sudo service heat-engine restart
#sudo service heat-api restart

13)
Confirm that your heat setup is working


* IP of Devstack VM : 192.168.56.102
* IP of Heat Standalone VM : 127.0.0.1


a)
Important Step.

* set accessable endpoints for your main OpenSatck setup. endpoints should be accessable from your heat VM.
http://fosshelp.blogspot.com/2014/07/openstack-devstack-how-to-set-custom.html

b)
b1)

Find the id of the admin tenant. Try to run this command from machine where you installed heat.
* Here --os-auth-url http://192.168.56.102:35357/v2.0 is the endpoint of keystone running in your main OpenStack Setup.
#keystone --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --debug tenant-list

b2)
Add the id of the admin tenant in --heat-url option and try to execute the command stack-list
* Find id of admin tenant and add in --heat-url , otherwise you will get error "Authentication required"
#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83 --os-no-client-auth --debug stack-list

### OR ###(not working now, bug, may be work later after fix)
#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/'%(tenant_id)s' --os-no-client-auth --debug stack-list

b3)
Create stack (working)

* Tail "heat-api.conf" and "heat-engine.conf" and run below command and verify that logs are comming, that means our heat setup is working.
* Find id of admin tenant and add in --heat-url , otherwise you will get error "Authentication required"
* --os-no-client-auth is also required
#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/832be22ed5ef4533a7daa53c895e4606 --os-no-client-auth --debug stack-create mystack1 -f https://raw.githubusercontent.com/openstack/heat-templates/master/hot/hello_world.yaml -P "db_password=123456"


b4)
* Add new KeyName

#nova --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --debug keypair-add  k1

* List keypairs
#nova --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --debug keypair-list

* Find imageid
#nova --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --debug image-list

b5)
Working command (Tested)

#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83 --os-no-client-auth --debug stack-create mystack1 -f https://raw.githubusercontent.com/openstack/heat-templates/master/hot/hello_world.yaml -P "db_password=P23456" -P "KeyName=k1" -P "ImageId=13ad8950-1f00-4587-8d3c-dd726265de08"

b6)
List and Check the status of created stack

#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83 --os-no-client-auth --debug stack-list

b7)
Find the Ip of the VM created by stack by listing the VMs

#nova --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --debug list

b8)
Download keypair

#nova --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --debug keypair-show k2

b9)
Delete Stack

#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83 --os-no-client-auth --debug stack-delete 8befad68-44ba-4f7d-9a4c-ff68d458decf

b10)
Create stack with our custom template "hello_world.yaml" (Working)

#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83 --os-no-client-auth --debug stack-create mystack2 -f hello_world.yaml -P "KeyName=k2" -P "ImageId=13ad8950-1f00-4587-8d3c-dd726265de08"

14)
Important Liks


a)
Note: Read following README.md
https://github.com/puppetlabs/puppetlabs-havana/blob/master/README.md
https://github.com/stackforge/puppet-openstack/blob/master/README.md

b)
Note: Read following docs
* Heat install-guide
http://docs.openstack.org/trunk/install-guide/install/apt/content/ch_heat.html

* Heat config-reference
http://docs.openstack.org/trunk/config-reference/content/ch_configuring-openstack-orchestration.html

c)
Working Repo from IRC guy
https://github.com/sajuptpm/puppet-openstack-cloud/

c1)
Starting Point
https://github.com/sajuptpm/puppet-openstack-cloud/blob/master/manifests/orchestration.pp

c2)
Then, move to
https://github.com/sajuptpm/puppet-openstack-cloud/blob/master/manifests/orchestration/api.pp
https://github.com/sajuptpm/puppet-openstack-cloud/blob/master/manifests/orchestration/engine.pp

d)
Example
https://github.com/stackforge/puppet-heat/blob/master/examples/site.pp


Tuesday, July 8, 2014

OpenStack Heat flow of stack-create action from heatclient to heat-api to heat-engine

OpenStack How to heat-api validates token against keystone
http://fosshelp.blogspot.com/2014/07/openstack-how-to-heat-api-validates.html

OpenStack HeatCLI and heatclient flow of stack-create action
http://fosshelp.blogspot.com/2014/07/openstack-cli-and-heatclient-flow-of.html

OpenStack heat-api flow of stack-create action
http://fosshelp.blogspot.com/2014/07/openstack-heat-api-flow-of-stack-create.html

OpenStack heat-engine flow of stack-create action
http://fosshelp.blogspot.com/2014/07/openstack-heat-engine-flow-of-stack.html





OpenStack How to heat-api validates token against keystone

1)
http://fosshelp.blogspot.in/2014/03/how-to-openstack-api-and-wsgi-api.html

2)
vim /etc/heat/api-paste.ini

# heat-api pipeline
[pipeline:heat-api]
pipeline = faultwrap ssl versionnegotiation authurl authtoken context apiv1app

[filter:faultwrap]
paste.filter_factory = heat.common.wsgi:filter_factory
heat.filter_factory = heat.api.openstack:faultwrap_filter

[filter:ssl]
paste.filter_factory = heat.common.wsgi:filter_factory
heat.filter_factory = heat.api.openstack:sslmiddleware_filter

[filter:versionnegotiation]
paste.filter_factory = heat.common.wsgi:filter_factory
heat.filter_factory = heat.api.openstack:version_negotiation_filter

# Middleware to set auth_url header appropriately
[filter:authurl]
paste.filter_factory = heat.common.auth_url:filter_factory


# Auth middleware that validates token against keystone
[filter:authtoken]
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory <===


[filter:context]
paste.filter_factory = heat.common.context:ContextMiddleware_filter_factory

[app:apiv1app]
paste.app_factory = heat.common.wsgi:app_factory
heat.app_factory = heat.api.openstack.v1:API


3)
authurl filter

/usr/lib/python2.7/dist-packages/heat/common/auth_url.py

from oslo.config import cfg
from webob.exc import HTTPBadRequest
from webob.exc import HTTPUnauthorized

from heat.common import wsgi
from heat.openstack.common import importutils

class AuthUrlFilter(wsgi.Middleware):

    def __init__(self, app, conf):
        super(AuthUrlFilter, self).__init__(app)
        self.conf = conf
        self.auth_url = self._get_auth_url() <===

    def _get_auth_url(self):
        if 'auth_uri' in self.conf:
            return self.conf['auth_uri']
        else:
            # Import auth_token to have keystone_authtoken settings setup.
            auth_token_module = 'keystoneclient.middleware.auth_token' <===
            importutils.import_module(auth_token_module) <===
            return cfg.CONF.keystone_authtoken.auth_uri <===


def filter_factory(global_conf, **local_conf):
    conf = global_conf.copy()
    conf.update(local_conf)

    def auth_url_filter(app):
        return AuthUrlFilter(app, conf)
    return auth_url_filter

4)
authtoken filter

/usr/lib/python2.7/dist-packages/keystoneclient/middleware/auth_token.py

"""
TOKEN-BASED AUTH MIDDLEWARE

This WSGI component:

* Verifies that incoming client requests have valid tokens by validating
  tokens with the auth service.
* Rejects unauthenticated requests
* SM:Please read the doc string of above "auth_token.py" file.

Refer to: http://docs.openstack.org/developer/python-keystoneclient/
middlewarearchitecture.html
"""

####SM:Read conf from /etc/heat/heat.conf file
opts = [
    cfg.StrOpt('auth_admin_prefix',
               default='',
               help='Prefix to prepend at the beginning of the path'),
    cfg.StrOpt('auth_host',
               default='127.0.0.1',
               help='Host providing the admin Identity API endpoint'),
    cfg.IntOpt('auth_port',
               default=35357,
               help='Port of the admin Identity API endpoint'),
    cfg.StrOpt('auth_protocol',
               default='https',
               help='Protocol of the admin Identity API endpoint'
               '(http or https)'),
    cfg.StrOpt('auth_uri',
               default=None,
               help='Complete public Identity API endpoint'),
]

####SM:Read
CONF = cfg.CONF
CONF.register_opts(opts, group='keystone_authtoken')


def filter_factory(global_conf, **local_conf):
    """Returns a WSGI filter app for use with paste.deploy."""
    conf = global_conf.copy()
    conf.update(local_conf)

    def auth_filter(app):
        return AuthProtocol(app, conf)
    return auth_filter

class AuthProtocol(object):
    """Auth Middleware that handles authenticating client calls."""

    def __init__(self, app, conf):
        self.LOG = logging.getLogger(conf.get('log_name', __name__))
        self.LOG.info('Starting keystone auth_token middleware')
        self.conf = conf
        self.app = app
        auth_host = self._conf_get('auth_host')
        auth_port = int(self._conf_get('auth_port'))
        self.auth_uri = self._conf_get('auth_uri')
        self.admin_token = self._conf_get('admin_token')

    def _conf_get(self, name):
        # try config from paste-deploy first
        if name in self.conf:
            return self.conf[name]
        else:
            return CONF.keystone_authtoken[name]

    def __call__(self, env, start_response): <===IMP
        """Handle incoming request.

        Authenticate send downstream on success. Reject request if
        we can't authenticate.

        """
        self._remove_auth_headers(env)
        user_token = self._get_user_token_from_header(env) <===
        token_info = self._validate_user_token(user_token, env) <===
        env['keystone.token_info'] = token_info
        user_headers = self._build_user_headers(token_info)
        self._add_headers(env, user_headers)
        return self.app(env, start_response) <===

    def _get_user_token_from_header(self, env):
        """Get token id from request.

        :param env: wsgi request environment
        :return token id
        :raises InvalidUserToken if no token is provided in request
        """
        token = self._get_header(env, 'X-Auth-Token',
                                 self._get_header(env, 'X-Storage-Token'))
        if token:
            return token

    def _validate_user_token(self, user_token, env, retry=True):
        """Authenticate user using PKI

        :param user_token: user's token id
        :param retry: Ignored, as it is not longer relevant
        :return uncrypted body of the token if the token is valid
        :raise InvalidUserToken if token is rejected
        :no longer raises ServiceError since it no longer makes RPC

        """
        token_id = cms.cms_hash_token(user_token)
        cached = self._cache_get(token_id)
        if cached:
            return cached
        if cms.is_ans1_token(user_token):
            verified = self.verify_signed_token(user_token) <===
            data = jsonutils.loads(verified)
        else:
            data = self.verify_uuid_token(user_token, retry) <===
        expires = confirm_token_not_expired(data) <===
        self._confirm_token_bind(data, env) <===

        self._cache_put(token_id, data, expires)
        return data

    def verify_uuid_token(self, user_token, retry=True):
        """Authenticate user token with keystone.

        :param user_token: user's token id
        :param retry: flag that forces the middleware to retry
                      user authentication when an indeterminate
                      response is received. Optional.
        :return: token object received from keystone on success
        :raise InvalidUserToken: if token is rejected
        :raise ServiceError: if unable to authenticate token

        """
        # Determine the highest api version we can use.
        if not self.auth_version:
            self.auth_version = self._choose_api_version()

        if self.auth_version == 'v3.0':
            headers = {'X-Auth-Token': self.get_admin_token(),
                       'X-Subject-Token': safe_quote(user_token)}
            path = '/v3/auth/tokens'
            if not self.include_service_catalog:
                # NOTE(gyee): only v3 API support this option
                path = path + '?nocatalog'
            response, data = self._json_request(
                'GET',
                path,
                additional_headers=headers)

        else:
            headers = {'X-Auth-Token': self.get_admin_token()}
            response, data = self._json_request(
                'GET',
                '/v2.0/tokens/%s' % safe_quote(user_token),
                additional_headers=headers)


        if response.status_code == 200:
            return data
        if response.status_code == 404:
            self.LOG.warn("Authorization failed for token")
            raise InvalidUserToken('Token authorization failed')

5)
apiv1app filter


5a)paste.app_factory = heat.common.wsgi:app_factory

/usr/lib/python2.7/dist-packages/heat/common/wsgi.py

class AppFactory(BasePasteFactory):

    """A Generic paste.deploy app factory.

    This requires heat.app_factory to be set to a callable which returns a
    WSGI app when invoked. The format of the name is : e.g.

      [app:apiv1app]
      paste.app_factory = heat.common.wsgi:app_factory
      heat.app_factory = heat.api.cfn.v1:API

    The WSGI app constructor must accept a ConfigOpts object and a local config
    dict as its two arguments.
    """

    KEY = 'heat.app_factory'

    def __call__(self, global_conf, **local_conf):
        """The actual paste.app_factory protocol method."""
        factory = self._import_factory(local_conf)
        return factory(self.conf, **local_conf)

5b)
heat.app_factory = heat.api.openstack.v1:API

/usr/lib/python2.7/dist-packages/heat/api/openstack/v1/__init__.py

class API(wsgi.Router):
    """
    WSGI router for Heat v1 ReST API requests.
    """
    def __init__(self, conf, **local_conf):
        self.conf = conf
        mapper = routes.Mapper()

        # Stacks
        stacks_resource = stacks.create_resource(conf)
        with mapper.submapper(controller=stacks_resource,
                              path_prefix="/{tenant_id}") as stack_mapper:

            # Template handling
            stack_mapper.connect("template_validate",
                                 "/validate",
                                 action="validate_template",
                                 conditions={'method': 'POST'})
            stack_mapper.connect("resource_types",
                                 "/resource_types",
                                 action="list_resource_types",
                                 conditions={'method': 'GET'})
            stack_mapper.connect("resource_schema",
                                 "/resource_types/{type_name}",
                                 action="resource_schema",
                                 conditions={'method': 'GET'})
            stack_mapper.connect("generate_template",
                                 "/resource_types/{type_name}/template",
                                 action="generate_template",
                                 conditions={'method': 'GET'})
            ---- blabla ----                    
        super(API, self).__init__(mapper)


OpenStack heat-engine flow of stack-create action

1)
/usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/amqp.py

class ProxyCallback(_ThreadPoolWithWait):
    """Calls methods on a proxy object based on method and args."""
   
    def __call__(self, message_data):
        self.pool.spawn_n(self._process_data, ctxt, version, method, namespace, args)   
   
    def _process_data(self, ctxt, version, method, namespace, args):
        """Process a message in a new thread.

        If the proxy object we have has a dispatch method
        (see rpc.dispatcher.RpcDispatcher), pass it the version,
        method, and args and let it dispatch as appropriate.  If not, use
        the old behavior of magically calling the specified method on the
        proxy we have here.
        """
        rval = self.proxy.dispatch(ctxt, version, method, namespace, **args) <===
        ctxt.reply(rval, None, connection_pool=self.connection_pool)

2)
/usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/dispatcher.py

    def dispatch(self, ctxt, version, method, namespace, **kwargs):
        """Dispatch a message based on a requested version.

        :param ctxt: The request context
        :param method: The method requested to be called by the incoming
                       message.
        :param namespace: The namespace for the requested method.  If None,
                          the dispatcher will look for a method on a callback
                          object with no namespace set.
        :param kwargs: A dict of keyword arguments to be passed to the method.
        """
       
        import pdb
        pdb.set_trace()

       
        kwargs = self._deserialize_args(ctxt, kwargs)
        result = getattr(proxyobj, method)(ctxt, **kwargs)
        return self.serializer.serialize_entity(ctxt, result)


IMP (Debug)
===========

a)
Stop "heat-engine"

#sudo service heat-engine stop
or
#ps -aux | grep heat
#sudo kill -9 pid pid


b)
Run "heat-engine" manually

#sudo /usr/bin/heat-engine --config-file /etc/heat/heat.conf

c)
Run the command "#heat create-stack"


d)
(Pdb) method
u'create_stack' <=====

(Pdb) namespace

(Pdb) kwargs
blabal

(Pdb) ctxt


(Pdb) ctxt.request_id
u'req-ffe57677-8b8a-4ec3-9c21-9786c1ee8f24'

(Pdb) getattr(proxyobj, method)
>

3)
/usr/lib/python2.7/dist-packages/heat/engine/service.py

def request_context(func):
    @functools.wraps(func)
    def wrapped(self, ctx, *args, **kwargs):
        if ctx is not None and not isinstance(ctx, context.RequestContext):
            ctx = context.RequestContext.from_dict(ctx.to_dict())
        try:
            return func(self, ctx, *args, **kwargs)
        except exception.HeatException:
            raise rpc_common.ClientException()
    return wrapped

    @request_context    def create_stack(self, cnxt, stack_name, template, params, files, args):
        """
        The create_stack method creates a new stack using the template
        provided.
        Note that at this stage the template has already been fetched from the
        heat-api process if using a template-url.

        :param cnxt: RPC context.
        :param stack_name: Name of the stack you want to create.
        :param template: Template of stack you want to create.
        :param params: Stack Input Params
        :param files: Files referenced from the template
        :param args: Request parameters/args passed from API
        """
        def _stack_create(stack):
            #Create a stack, and create the periodic task if successful
            stack.create() <===       
       
        stack = parser.Stack(cnxt, stack_name, tmpl,
                             env, **common_params)

        self._validate_deferred_auth_context(cnxt, stack)

        stack.validate() <===

        stack.store() <===

        self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id,
                                              _stack_create, stack)



4)
/usr/lib/python2.7/dist-packages/heat/engine/parser.py

class Stack(collections.Mapping):

    ACTIONS = (CREATE, DELETE, UPDATE, ROLLBACK, SUSPEND, RESUME, ADOPT
               ) = ('CREATE', 'DELETE', 'UPDATE', 'ROLLBACK', 'SUSPEND',
                    'RESUME', 'ADOPT')

    STATUSES = (IN_PROGRESS, FAILED, COMPLETE
                ) = ('IN_PROGRESS', 'FAILED', 'COMPLETE')


    def total_resources(self):
        '''
        Return the total number of resources in a stack, including nested
        stacks below.
        '''

    @classmethod
    def load(
cls, context, stack_id=None, stack=None, resolve_data=True,
             parent_resource=None, show_deleted=True):
        '''Retrieve a Stack from the database.'''

    def store(self, backup=False):
        '''
        Store the stack in the database and return its ID
        If self.id is set, we update the existing stack
        '''
        s = {
            'name': self.name,
            'raw_template_id': self.t.store(self.context),
            'parameters': self.env.user_env_as_dict(),
            'owner_id': self.owner_id,
            'username': self.context.username,
            'tenant': self.tenant_id,
            'action': self.action,
        }
       
        new_creds = db_api.user_creds_create(self.context) <===
        new_s = db_api.stack_create(self.context, s) <===


    def validate(self):
        '''
        Validates the template.
        '''

    def state_set(self, action, status, reason):
        '''Update the stack state in the database.'''
        stack = db_api.stack_get(self.context, self.id)
        stack.update_and_save({'action': action,
                                   'status': status,
                                   'status_reason': reason})

    def create(self):
        '''
        Create the stack and all of the resources.
        '''

    @scheduler.wrappertask
    def stack_task(self, action, reverse=False, post_func=None):
        '''
        A task to perform an action on the stack and all of the resources
        in forward or reverse dependency order as specfifed by reverse
        '''

    def delete(self, action=DELETE, backup=False):
        '''
        Delete all of the resources, and then the stack itself.
        The action parameter is used to differentiate between a user
        initiated delete and an automatic stack rollback after a failed
        create, which amount to the same thing, but the states are recorded
        differently.
        '''

4)
DB API


4a)
Heat db api

/usr/lib/python2.7/dist-packages/heat/db/api.py

from heat.openstack.common.db import api as db_api

_BACKEND_MAPPING = {'sqlalchemy': 'heat.db.sqlalchemy.api'} <===
IMPL = db_api.DBAPI(backend_mapping=_BACKEND_MAPPING) <===


def user_creds_create(context):
    return IMPL.user_creds_create(context)

def stack_create(context, values):
    return IMPL.stack_create(context, values)

4b)
common db api

/usr/lib/python2.7/dist-packages/heat/openstack/common/db/api.py

from oslo.config import cfg
from heat.openstack.common import importutils

db_opts = [
    cfg.StrOpt('backend',
               default='sqlalchemy',
               deprecated_name='db_backend',
               deprecated_group='DEFAULT',
               help='The backend to use for db'),
]

CONF = cfg.CONF
CONF.register_opts(db_opts, 'database')

class DBAPI(object):
    def __init__(self, backend_mapping=None):
        backend_name = CONF.database.backend
        backend_path = backend_mapping.get(backend_name, backend_name) <===
        backend_mod = importutils.import_module(backend_path) <===
        self.__backend = backend_mod.get_backend() <===


4c)
sqlalchemy db api

/usr/lib/python2.7/dist-packages/heat/db/sqlalchemy/api.py

import sqlalchemy
from sqlalchemy.orm.session import Session
from heat.db.sqlalchemy import models
from heat.openstack.common.db.sqlalchemy import session as db_session

def stack_create(context, values):
    stack_ref = models.Stack() <===
    stack_ref.update(values) <===
    stack_ref.save(_session(context)) <===

    return stack_ref

4d)
/usr/lib/python2.7/dist-packages/heat/db/sqlalchemy/models.py

class Stack(BASE, HeatBase, SoftDelete):
    """Represents a stack created by the heat engine."""

    __tablename__ = 'stack'

    id = sqlalchemy.Column(sqlalchemy.String(36), primary_key=True,
                           default=lambda: str(uuid.uuid4()))
    name = sqlalchemy.Column(sqlalchemy.String(255))
    raw_template_id = sqlalchemy.Column(
        sqlalchemy.Integer,
        sqlalchemy.ForeignKey('raw_template.id'),
        nullable=False)
    raw_template = relationship(RawTemplate, backref=backref('stack'))
    username = sqlalchemy.Column(sqlalchemy.String(256))
    tenant = sqlalchemy.Column(sqlalchemy.String(256))
    action = sqlalchemy.Column('action', sqlalchemy.String(255))
    status = sqlalchemy.Column('status', sqlalchemy.String(255))
    status_reason = sqlalchemy.Column('status_reason', sqlalchemy.String(255))
    parameters = sqlalchemy.Column('parameters', Json)
    user_creds_id = sqlalchemy.Column(
        sqlalchemy.Integer,
        sqlalchemy.ForeignKey('user_creds.id'),
        nullable=False)
    owner_id = sqlalchemy.Column(sqlalchemy.String(36), nullable=True)
    timeout = sqlalchemy.Column(sqlalchemy.Integer)
    disable_rollback = sqlalchemy.Column(sqlalchemy.Boolean, nullable=False)
    stack_user_project_id = sqlalchemy.Column(sqlalchemy.String(64),
                                              nullable=True)
    updated_at = sqlalchemy.Column(sqlalchemy.DateTime)

5)

Next : OpenStack heat-api flow of stack-create action
http://fosshelp.blogspot.com/2014/07/openstack-heat-api-flow-of-stack-create.html




Monday, July 7, 2014

OpenStack heat-api flow of stack-create action

#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83 --os-no-client-auth --debug stack-create stk1 -f https://raw.githubusercontent.com/openstack/heat-templates/master/hot/hello_world.yaml -P "db_password=P23456" -P "KeyName=k2" -P "ImageId=13ad8950-1f00-4587-8d3c-dd726265de08"

* Please note --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83

* "8004" is the port where "heat-api" is running

1)

/usr/lib/python2.7/dist-packages/heat/api/openstack/v1/__init__.py

from heat.api.openstack.v1 import stacks

class API(wsgi.Router):
    def __init__(self, conf, **local_conf):
   
        stacks_resource = stacks.create_resource(conf) <====IMP
       
        with mapper.submapper(controller=stacks_resource,
                              path_prefix="/{tenant_id}") as stack_mapper:   
   
            stack_mapper.connect("stack_create",
                                 "/stacks",
                                 action="create", <====IMP
                                 conditions={'method': 'POST'})


2)
/usr/lib/python2.7/dist-packages/heat/api/openstack/v1/stacks.py

def create_resource(options):
    return wsgi.Resource(StackController(options), deserializer, serializer)

class StackController(object):

    REQUEST_SCOPE = 'stacks'

    def __init__(self, options):
        self.options = options
        self.rpc_client = rpc_client.EngineClient() <====IMP

    @util.policy_enforce
    def create(self, req, body):
        """
        Create a new stack
        """
        data = InstantiationData(body)

        import pdb
        pdb.set_trace()

        result = self.rpc_client.create_stack(req.context,
                                              data.stack_name(),
                                              data.template(),
                                              data.environment(),
                                              data.files(),
                                              data.args())

        formatted_stack = stacks_view.format_stack(
            req,
            {engine_api.STACK_ID: result}
        )
        return {'stack': formatted_stack}

IMP (Debug)
===============

a)
Add pdb.set_trace()

b)
* Stop "heat-api"
#sudo service heat-api stop

c)
Start "heat-api" manually

#sudo /usr/bin/heat-api --config-file /etc/heat/heat.conf

d)
Run the "#heat create-stack" command and you can see the "pdb" prompt.

e)
(Pdb) req


(Pdb) req.context


(Pdb) req.context.request_id
'req-fb22b0df-d05a-4b35-9b73-f9300097e067'

(Pdb) dir(req.context)
blabla

-------

(Pdb) data


(Pdb) dir(data)
blabla

(Pdb) type(data.data)

* data.data will contains all data from the template

(Pdb) dir(req)
blabla

--------

(Pdb) self.rpc_client


(Pdb) dir(self.rpc_client)
blabla

--------

3)
/usr/lib/python2.7/dist-packages/heat/rpc/client.py

from heat.rpc import api
import heat.openstack.common.rpc.proxy

class EngineClient(heat.openstack.common.rpc.proxy.RpcProxy):

    def create_stack(self, ctxt, stack_name, template, params, files, args):
        return self.call(ctxt,
                         self.make_msg('create_stack', stack_name=stack_name,
                                       template=template,
                                       params=params, files=files, args=args))


3a)
/usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/proxy.py

class RpcProxy(object):

    def call(self, context, msg, topic=None, version=None, timeout=None):
        """
        rpc.call() a remote method.
        :param context: The request context <===
        :param msg: The message to send, including the method and args. <===
        :param topic: Override the topic for this message.  <===
        """
        import pdb
        pdb.set_trace()
       
        real_topic = self._get_topic(topic)
        result = rpc.call(context, real_topic, msg, timeout)


    def multicall(self, context, msg, topic=None, version=None, timeout=None):
        """rpc.multicall() a remote method.""

    def cast(self, context, msg, topic=None, version=None):
        """rpc.cast() a remote method.""
       
    def fanout_cast(self, context, msg, topic=None, version=None):
        """rpc.fanout_cast() a remote method."""       
       
    def cast_to_server(self, context, server_params, msg, topic=None, version=None):
        """rpc.cast_to_server() a remote method."""

    def fanout_cast_to_server(self, context, server_params, msg, topic=None, version=None):
        """rpc.fanout_cast_to_server() a remote method."""

IMP (Debug)
===============


(Pdb) topic

(Pdb) real_topic
'engine' <===== IMP

(Pdb) context


(Pdb) context.request_id
'req-e979ea7d-d392-4a79-a6da-4c7a661cd2b7'

(Pdb) rpc


----

* Check the module level varibale "rpc_opts" of /usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/__init__.py

(Pdb) rpc.rpc_opts
blabla

(Pdb) type(rpc.rpc_opts)


(Pdb) dir(rpc.rpc_opts[0])
blabla

(Pdb) [(x.name,x.default) for x in rpc.rpc_opts] <=== IMP

[
('rpc_backend', 'heat.openstack.common.rpc.impl_kombu'),  <===
('rpc_thread_pool_size', 64), ('rpc_conn_pool_size', 30),
('rpc_response_timeout', 60), ('rpc_cast_timeout', 30),
('allowed_rpc_exception_modules', ['nova.exception', 'cinder.exception', 'exceptions']),
('fake_rabbit', False), ('control_exchange', 'heat')
]

* Note the "rpc_backend"

------

* Check the module level varibale "CONF" of /usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/__init__.py

(Pdb) rpc.CONF


(Pdb) dir(rpc.CONF)
blabla

##Get all registered Configs
(Pdb) from pprint import pprint as pp
(Pdb) pp(rpc.CONF.items()) <====

blabla

(Pdb) rpc.CONF.rpc_backend
'heat.openstack.common.rpc.impl_kombu'


* Note the "rpc_backend"

3b)
/usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/__init__.py

from oslo.config import cfg

rpc_opts = [blabla] <====
CONF = cfg.CONF
CONF.register_opts(rpc_opts) <====

def cast(context, topic, msg):
def fanout_cast(context, topic, msg):
def multicall(context, topic, msg, timeout=None):
def notify(context, topic, msg, envelope=False):
def cast_to_server(context, server_params, topic, msg):
def fanout_cast_to_server(context, server_params, topic, msg):

def call(context, topic, msg, timeout=None):

    """
    Invoke a remote method that returns something.

    :param context: Information that identifies the user that has made this
                    request.
    :param topic: The topic to send the rpc message to.  This correlates to the
                  topic argument of
                  openstack.common.rpc.common.Connection.create_consumer()
                  and only applies when the consumer was created with
                  fanout=False.
    :param msg: This is a dict in the form { "method" : "method_to_invoke",
                                             "args" : dict_of_kwargs }
    """
    return _get_impl().call(CONF, context, topic, msg, timeout)


def _get_impl():
    _RPCIMPL = importutils.import_module(CONF.rpc_backend)
    return _RPCIMPL

* Note, here "CONF.rpc_backend" is 'heat.openstack.common.rpc.impl_kombu'

3c)
Since, "CONF.rpc_backend" is 'heat.openstack.common.rpc.impl_kombu'

http://kombu.readthedocs.org/en/latest/
http://kombu.readthedocs.org/en/latest/userguide/examples.html

/usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/impl_kombu.py

import kombu
import kombu.connection
import kombu.entity
import kombu.messaging

from heat.openstack.common.rpc import amqp as rpc_amqp <===
from oslo.config import cfg

kombu_opts = [blabla] <===
cfg.CONF.register_opts(kombu_opts)

def call(conf, context, topic, msg, timeout=None):
    """Sends a message on a topic and wait for a response."""
    return rpc_amqp.call(
        conf, context, topic, msg, timeout,
        rpc_amqp.get_connection_pool(conf, Connection)) <===



def multicall(conf, context, topic, msg, timeout=None):
    """Make a call that returns multiple times."""

def cast(conf, context, topic, msg):
    """Sends a message on a topic without waiting for a response."""

def fanout_cast(conf, context, topic, msg):
    """Sends a message on a fanout exchange without waiting for a response."""

def cast_to_server(conf, context, server_params, topic, msg):
    """Sends a message on a topic to a specific server."""

def fanout_cast_to_server(conf, context, server_params, topic, msg):
    """Sends a message on a fanout exchange to a specific server."""

def notify(conf, context, topic, msg, envelope):
    """Sends a notification event on a topic."""

class Connection(object):
    blabla

3d)
/usr/lib/python2.7/dist-packages/heat/openstack/common/rpc/amqp.py

def multicall(conf, context, topic, msg, timeout, connection_pool):
    """Make a call that returns multiple times."""
    conn.topic_send(topic, rpc_common.serialize_msg(msg), timeout)

def call(conf, context, topic, msg, timeout, connection_pool):
    """Sends a message on a topic and wait for a response."""

def cast(conf, context, topic, msg, connection_pool):
    """Sends a message on a topic without waiting for a response."""

def fanout_cast(conf, context, topic, msg, connection_pool):
    """Sends a message on a fanout exchange without waiting for a response."""

def cast_to_server(conf, context, server_params, topic, msg, connection_pool):
    """Sends a message on a topic to a specific server."""

def fanout_cast_to_server(conf, context, server_params, topic, msg,
                          connection_pool):

def notify(conf, context, topic, msg, connection_pool, envelope):
    """Sends a notification event on a topic."""

4)
Learn kombu.

http://kombu.readthedocs.org/en/latest/
http://kombu.readthedocs.org/en/latest/userguide/examples.html


OpenStack HeatCLI and heatclient flow of stack-create action

#heat --os-username admin --os-password nova --os-tenant-name admin --os-auth-url http://192.168.56.102:35357/v2.0 --heat-url http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83 --os-no-client-auth --debug stack-create stk1 -f https://raw.githubusercontent.com/openstack/heat-templates/master/hot/hello_world.yaml -P "db_password=P23456" -P "KeyName=k2" -P "ImageId=13ad8950-1f00-4587-8d3c-dd726265de08"

* "8004" is the port where "heat-api" is running

######### Heat CLI #########

1)
/usr/lib/python2.7/dist-packages/heatclient/shell.py

class HeatShell(object):
    def main(self, argv):
        client = heat_client.Client(api_version, endpoint, **kwargs)
        args.func(client, args)

2)
/usr/lib/python2.7/dist-packages/heatclient/v1/shell.py

def do_stack_create(hc, args):
    hc.stacks.create(**fields)
   
* Here "hc" is heat_client.Client()
* Check /usr/lib/python2.7/dist-packages/heatclient/v1/client.py
   
3)
/usr/lib/python2.7/dist-packages/heatclient/v1/stacks.py

class Stack(base.Resource):
    def create(self, **fields):
        return self.manager.create(self.identifier, **fields)

class StackManager(base.BaseManager):
    resource_class = Stack
   
    def create(self, **kwargs):
        """Create a stack."""
        headers = self.client.credentials_headers()
       
        import pdb
        pdb.set_trace()

       
        resp, body = self.client.json_request('POST', '/stacks',
                                              data=kwargs, headers=headers)

        return body

IMP (DEBUG)
===========


Add a break point and check the value following variables of "self.client".

###Keystone EndPoint
(Pdb) self.client.auth_url
'http://192.168.56.102:35357/v2.0'

###Endpoint where to send this request after keystone authentication
(Pdb) self.client.endpoint_url
'http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83'

(Pdb) self.client.endpoint
'http://127.0.0.1:8004/v1/5864a59a240e4a43bc3c17fcbd6cfd83'

* "8004" is the port where "heat-api" is running

4)
/usr/lib/python2.7/dist-packages/heatclient/v1/client.py

class Client(object):
    self.http_client = http.HTTPClient(*args, **kwargs)
    self.stacks = stacks.StackManager(self.http_client)

5)
/usr/lib/python2.7/dist-packages/heatclient/common/http.py

class HTTPClient(object):
    def json_request(self, method, url, **kwargs):
        resp = self._http_request(url, method, **kwargs)

    def _http_request(self, url, method, **kwargs):
        resp = requests.request(-----) <=== Make Restful Call
6)
Next : OpenStack heat-api flow of stack-create action

http://fosshelp.blogspot.com/2014/07/openstack-heat-api-flow-of-stack-create.html


Thursday, July 3, 2014

OpenStack Heat Puppet Error: Could not find dependency Exec[heat-dbsync] for Service[heat-engine] at /var/puppet/modules/heat/manifests/engine.pp:72


Fix
====

Specify the attribute "sql_connection" of class { '::heat':

sql_connection => "sqlite:////var/lib/heat/sqlite_db",









Friday, May 16, 2014

Howto OpenStack Heat orchestration devstack Havana with getting_started.template

1)
Create Keypair
----------------

#nova keypair-add heat_key > heat_key.priv
#chmod 600 heat_key.priv

2)
Open

vim /home/saju/openstack/heat_templates/heat-templates/cfn/F17/getting_started.template
https://github.com/openstack/heat-templates/blob/master/cfn/F17/getting_started.template

* Then Change "InstanceType": "m1.small" to "InstanceType": "m1.micro", if you get the error No valid host was found (NoValidHost).
* Change ImageId "F17-x86_64-cfntools" to "fedora-20.x86_64"

Example:
-------------
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Parameters" : {
    "KeyName" : {
      "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instance",
      "Type" : "String"
    }
  },

  "Resources" : {
    "MyInstance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "KeyName" : { "Ref" : "KeyName" },
        "ImageId" : "fedora-20.x86_64",
        "InstanceType": "m1.micro",
        "UserData" : { "Fn::Base64" : "80" }
      }
    }
  },
  "Outputs" : {
    "InstanceIp" : {
      "Value" : { "Fn::Join" : ["", ["ssh ec2-user@",
                                     {"Fn::GetAtt": ["MyInstance",
                                     "PublicIp"]}]]},
      "Description" : "My ssh command"
    }
  }
}


3)
Create Stack

#heat stack-create teststack7 -f /home/saju/openstack/heat_templates/heat-templates/cfn/F17/getting_started.template -P "KeyName=heat_key"

4)
List Stack

#heat stack-list

5)
Find resources of stack

#heat resource-list id_of_stack

6)
Delete Stack

#heat stack-delete id_of_stack

7)
localrc
------------

saju@ubuntu:~/openstack$ cat devstack/localrc
DATABASE_PASSWORD=nova
RABBIT_PASSWORD=nova
SERVICE_TOKEN=nova
SERVICE_PASSWORD=nova
ADMIN_PASSWORD=nova

OFFLINE=True

###To capture the screen output of OpenStack services in separate log files
SCREEN_LOGDIR=/home/saju/openstack/screen_dir

###To capture the screen output of OpenStack services in one log file
LOGFILE=/opt/stack/logs/stack.sh.log
VERBOSE=True

###Ceilometer
#enable_service ceilometer-acentral,ceilometer-collector,ceilometer-api,ceilometer-acompute,ceilometer-alarm-singleton,ceilometer-alarm-notifier
#EXTRA_OPTS=(notification_driver=nova.openstack.common.notifier.rabbit_notifier,ceilometer.compute.nova_notifier scheduler_default_filters=AllHostsFilter)

#http://docs.openstack.org/developer/heat/getting_started/on_devstack.html#configure-devstack-to-enable-ceilometer-if-using-alarms
CEILOMETER_BACKEND=mongo
enable_service ceilometer-acompute ceilometer-acentral ceilometer-collector ceilometer-api
enable_service ceilometer-alarm-notifier ceilometer-alarm-evaluator

###Heat
enable_service heat,h-api,h-api-cfn,h-api-cw,h-eng
#IMAGE_URLS+=",http://fedorapeople.org/groups/heat/prebuilt-jeos-images/F17-i386-cfntools.qcow2,http://fedorapeople.org/groups/heat/prebuilt-jeos-images/F17-x86_64-cfntools.qcow2"

IMAGE_URLS+=",http://fedorapeople.org/groups/heat/prebuilt-jeos-images/F19-x86_64-cfntools.qcow2"
IMAGE_URLS+=",http://mirror.chpc.utah.edu/pub/fedora/linux/releases/20/Images/x86_64/Fedora-x86_64-20-20131211.1-sda.qcow2"

###64bit image (~660MB)
IMAGE_URLS+=",http://download.fedoraproject.org/pub/fedora/linux/updates/20/Images/x86_64/Fedora-x86_64-20-20140407-sda.qcow2"
###32bit image (~640MB)
IMAGE_URLS+=",http://download.fedoraproject.org/pub/fedora/linux/updates/20/Images/i386/Fedora-i386-20-20140407-sda.qcow2"

###Heat, Havana, Working image for the template heat-templates/cfn/F17/getting_started.template
IMAGE_URLS+=",http://cloud.fedoraproject.org/fedora-20.x86_64.qcow2"
##ssh -i heat_key.priv ec2-user@10.0.0.2

###Network configuration.
#HOST_IP should be the same as the IP you used for the private network.
# The combination of FLAT_INTERFACE and PUBLIC_INTERFACE indicates that OpenStack should
# bridge network traffic over eth1.
HOST_IP=192.168.56.101
HOST_IP_IFACE=eth1
FLAT_INTERFACE=br100
PUBLIC_INTERFACE=eth1
FLOATING_RANGE=192.168.56.224/27