diff --git a/example.py b/example.py index 3d833c96..e7bff062 100644 --- a/example.py +++ b/example.py @@ -1,4 +1,5 @@ import click +import json import requests import sys import time @@ -11,6 +12,7 @@ from solar.core import validation from solar.interfaces.db import get_db + @click.group() def main(): pass @@ -26,9 +28,9 @@ def deploy(): node1 = resource.create('node1', 'resources/ro_node/', {'ip': '10.0.0.3', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev1/virtualbox/private_key', 'ssh_user': 'vagrant'}) node2 = resource.create('node2', 'resources/ro_node/', {'ip': '10.0.0.4', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev2/virtualbox/private_key', 'ssh_user': 'vagrant'}) - rabbitmq_service1 = resource.create('rabbitmq_service1', 'resources/rabbitmq_service/', {'ssh_user':'', 'ip':'','management_port':'15672', 'port':'5672', 'ssh_key':'', 'container_name': 'rabbitmq_service1', 'image': 'rabbitmq:3-management'}) - openstack_vhost = resource.create('openstack_vhost', 'resources/rabbitmq_vhost/', {'ssh_user':'', 'ip':'', 'ssh_key':'', 'vhost_name' : 'openstack', 'container_name':''}) - openstack_rabbitmq_user = resource.create('openstack_rabbitmq_user', 'resources/rabbitmq_user/', {'ssh_user':'', 'ip':'', 'ssh_key':'', 'vhost_name' : '', 'user_name':'openstack', 'password':'openstack_password', 'container_name':''}) + rabbitmq_service1 = resource.create('rabbitmq_service1', 'resources/rabbitmq_service/', {'ssh_user': '', 'ip': '','management_port': '15672', 'port': '5672', 'ssh_key': '', 'container_name': 'rabbitmq_service1', 'image': 'rabbitmq:3-management'}) + openstack_vhost = resource.create('openstack_vhost', 'resources/rabbitmq_vhost/', {'ssh_user': '', 'ip': '', 'ssh_key': '', 'vhost_name': 'openstack', 'container_name': ''}) + openstack_rabbitmq_user = resource.create('openstack_rabbitmq_user', 'resources/rabbitmq_user/', {'ssh_user': '', 'ip': '', 'ssh_key': '', 'vhost_name': '', 'user_name': 'openstack', 'password': 'openstack_password', 'container_name': ''}) mariadb_service1 = resource.create('mariadb_service1', 'resources/mariadb_service', {'image': 'mariadb', 'root_password': 'mariadb', 'port': 3306, 'ip': '', 'ssh_user': '', 'ssh_key': ''}) keystone_db = resource.create('keystone_db', 'resources/mariadb_db/', {'db_name': 'keystone_db', 'login_password': '', 'login_user': 'root', 'login_port': '', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) @@ -40,14 +42,30 @@ def deploy(): keystone_config2 = resource.create('keystone_config2', 'resources/keystone_config/', {'config_dir': '/etc/solar/keystone', 'ip': '', 'ssh_user': '', 'ssh_key': '', 'admin_token': 'admin', 'db_password': '', 'db_name': '', 'db_user': '', 'db_host': '', 'db_port': ''}) keystone_service2 = resource.create('keystone_service2', 'resources/keystone_service/', {'port': 5002, 'admin_port': 35358, 'image': '', 'ip': '', 'ssh_key': '', 'ssh_user': '', 'config_dir': ''}) - haproxy_keystone_config = resource.create('haproxy_keystone1_config', 'resources/haproxy_keystone_config/', {'name': 'keystone_config', 'listen_port':5000, 'servers':[], 'ports':[]}) - haproxy_config = resource.create('haproxy_config', 'resources/haproxy', {'ip': '', 'ssh_key': '', 'ssh_user': '', 'configs_names':[], 'configs_ports':[], 'listen_ports':[], 'configs':[], 'config_dir': ''}) - haproxy_service = resource.create('haproxy_service', 'resources/docker_container/', {'image': 'tutum/haproxy', 'ports': [], 'host_binds': [], 'volume_binds':[], 'ip': '', 'ssh_key': '', 'ssh_user': ''}) + haproxy_keystone_config = resource.create('haproxy_keystone_config', 'resources/haproxy_keystone_config/', {'name': 'keystone_config', 'listen_port': 5000, 'servers': [], 'ports':[]}) + haproxy_config = resource.create('haproxy_config', 'resources/haproxy', {'ip': '', 'ssh_key': '', 'ssh_user': '', 'configs_names': [], 'configs_ports': [], 'listen_ports': [], 'configs':[], 'config_dir': ''}) + haproxy_service = resource.create('haproxy_service', 'resources/docker_container/', {'image': 'tutum/haproxy', 'ports': [], 'host_binds': [], 'volume_binds': [], 'ip': '', 'ssh_key': '', 'ssh_user': ''}) - admin_tenant = resource.create('admin_tenant', 'resources/keystone_tenant', {'keystone_host': '', 'keystone_port':'', 'login_user': 'admin', 'admin_token':'', 'tenant_name' : 'admin', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) - admin_user = resource.create('admin_user', 'resources/keystone_user', {'keystone_host': '', 'keystone_port':'', 'login_user': 'admin', 'admin_token':'', 'tenant_name' : '', 'user_name': 'admin', 'user_password':'admin', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) - admin_role = resource.create('admin_role', 'resources/keystone_role', {'keystone_host': '', 'keystone_port':'', 'login_user': 'admin', 'admin_token':'', 'tenant_name' : '', 'user_name': '', 'role_name': 'admin', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) - keystone_service_endpoint = resource.create('keystone_service_endpoint', 'resources/keystone_service_endpoint/', {'ip':'', 'ssh_key' : '', 'ssh_user':'', 'admin_port':'', 'admin_token':'', 'adminurl':'http://{{ip}}:{{admin_port}}/v2.0', 'internalurl':'http://{{ip}}:{{port}}/v2.0', 'publicurl':'http://{{ip}}:{{port}}/v2.0', 'description':'OpenStack Identity Service', 'keystone_host':'', 'keystone_port':'', 'name':'keystone', 'port':'', 'type':'identity'}) + glance_db = resource.create('glance_db', 'resources/mariadb_db/', {'db_name': 'glance_db', 'login_password': '', 'login_user': 'root', 'login_port': '', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) + glance_db_user = resource.create('glance_db_user', 'resources/mariadb_user/', {'new_user_name': 'glance', 'new_user_password': 'glance', 'db_name': '', 'login_password': '', 'login_user': 'root', 'login_port': '', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) + + services_tenant = resource.create('glance_keystone_tenant', 'resources/keystone_tenant', {'keystone_host': '', 'keystone_port': '', 'login_user': 'admin', 'admin_token': '', 'tenant_name': 'services', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) + + glance_keystone_user = resource.create('glance_keystone_user', 'resources/keystone_user', {'user_name': 'glance_admin', 'user_password': 'password1234', 'tenant_name': 'service_admins', 'role_name': 'glance_admin', 'keystone_host': '', 'keystone_port': '', 'admin_token': '', 'ip': '', 'ssh_key': '', 'ssh_user': ''}) + glance_keystone_role = resource.create('glance_keystone_role', 'resources/keystone_role', {'keystone_host': '', 'keystone_port': '', 'login_user': 'admin', 'admin_token': '', 'tenant_name': '', 'user_name': '', 'role_name': 'admin', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) + + glance_config = resource.create('glance_config', 'resources/glance_config/', {'ip': '', 'ssh_key': '', 'ssh_user': '', 'keystone_ip': '', 'keystone_port': '', 'config_dir': {}, 'api_port': '', 'registry_port': '', 'mysql_ip': '', 'mysql_db': '', 'mysql_user': '', 'mysql_password': '', 'keystone_admin_user': '', 'keystone_admin_password': '', 'keystone_admin_port': '', 'keystone_admin_tenant': ''}) + glance_api_container = resource.create('glance_api_container', 'resources/glance_api_service/', {'image': 'cgenie/centos-rdo-glance-api', 'ports': [{'value': [{'value': 9292}]}], 'host_binds': [], 'volume_binds': [], 'db_password': '', 'keystone_password': '', 'keystone_admin_token': '', 'keystone_host': '', 'ip': '', 'ssh_key': '', 'ssh_user': ''}) + glance_registry_container = resource.create('glance_registry_container', 'resources/glance_registry_service/', {'image': 'cgenie/centos-rdo-glance-registry', 'ports': [{'value': [{'value': 9191}]}], 'host_binds': [], 'volume_binds': [], 'db_host': '', 'db_root_password': '', 'db_password': '', 'db_name': '', 'db_user': '', 'keystone_admin_tenant': '', 'keystone_password': '', 'keystone_user': '', 'keystone_admin_token': '', 'keystone_host': '', 'ip': '', 'ssh_key': '', 'ssh_user': ''}) + # TODO: admin_port should be refactored, we need to rethink docker + # container resource and make it common for all + # resources used in this demo + glance_api_endpoint = resource.create('glance_api_endpoint', 'resources/keystone_service_endpoint/', {'ip': '', 'ssh_key': '', 'ssh_user': '', 'admin_port': 9292, 'admin_token': '', 'adminurl': 'http://{{ip}}:{{admin_port}}', 'internalurl': 'http://{{ip}}:{{port}}', 'publicurl': 'http://{{ip}}:{{port}}', 'description': 'OpenStack Image Service', 'keystone_host': '', 'keystone_port': '', 'name': 'glance', 'port': 9292, 'type': 'image'}) + + admin_tenant = resource.create('admin_tenant', 'resources/keystone_tenant', {'keystone_host': '', 'keystone_port': '', 'login_user': 'admin', 'admin_token': '', 'tenant_name': 'admin', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) + admin_user = resource.create('admin_user', 'resources/keystone_user', {'keystone_host': '', 'keystone_port': '', 'login_user': 'admin', 'admin_token': '', 'tenant_name': '', 'user_name': 'admin', 'user_password': 'admin', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) + admin_role = resource.create('admin_role', 'resources/keystone_role', {'keystone_host': '', 'keystone_port': '', 'login_user': 'admin', 'admin_token': '', 'tenant_name': '', 'user_name': '', 'role_name': 'admin', 'ip': '', 'ssh_user': '', 'ssh_key': ''}) + keystone_service_endpoint = resource.create('keystone_service_endpoint', 'resources/keystone_service_endpoint/', {'ip': '', 'ssh_key': '', 'ssh_user': '', 'admin_port': '', 'admin_token': '', 'adminurl': 'http://{{ip}}:{{admin_port}}/v2.0', 'internalurl': 'http://{{ip}}:{{port}}/v2.0', 'publicurl': 'http://{{ip}}:{{port}}/v2.0', 'description': 'OpenStack Identity Service', 'keystone_host': '', 'keystone_port': '', 'name': 'keystone', 'port': '', 'type': 'identity'}) #### @@ -95,36 +113,69 @@ def deploy(): signals.connect(node2, haproxy_service) signals.connect(haproxy_config, haproxy_service, {'listen_ports': 'ports', 'config_dir': 'host_binds'}) - #keystone configuration + # keystone configuration signals.connect(keystone_config1, admin_tenant) signals.connect(keystone_service1, admin_tenant, {'admin_port': 'keystone_port', 'ip': 'keystone_host'}) signals.connect(admin_tenant, admin_user) signals.connect(admin_user, admin_role) signals.connect(keystone_config1, keystone_service_endpoint) - signals.connect(keystone_service1, keystone_service_endpoint, {'ip': 'keystone_host','admin_port':'admin_port', 'port':'port'}) + signals.connect(keystone_service1, keystone_service_endpoint, {'ip': 'keystone_host','admin_port': 'admin_port', 'port': 'port'}) signals.connect(keystone_service1, keystone_service_endpoint, {'admin_port': 'keystone_port'}) + # glance db + signals.connect(node1, glance_db) + signals.connect(mariadb_service1, glance_db, {'root_password': 'login_password', 'port': 'login_port'}) + signals.connect(node1, glance_db_user) + signals.connect(mariadb_service1, glance_db_user, {'root_password': 'login_password', 'port': 'login_port'}) + signals.connect(glance_db, glance_db_user, {'db_name': 'db_name'}) + + # glance keystone user + signals.connect(keystone_config1, services_tenant) + signals.connect(keystone_service1, services_tenant, {'admin_port': 'keystone_port', 'ip': 'keystone_host'}) + signals.connect(services_tenant, glance_keystone_user) # standard ip, ssh_key, ssh_user + signals.connect(glance_keystone_user, glance_keystone_role) + signals.connect(keystone_service1, glance_keystone_user, {'admin_port': 'keystone_port', 'ip': 'keystone_host'}) + signals.connect(keystone_config1, glance_keystone_user, {'admin_token': 'admin_token'}) + signals.connect(glance_keystone_user, glance_config, {'user_name': 'keystone_admin_user', 'user_password': 'keystone_admin_password', 'tenant_name': 'keystone_admin_tenant'}) + signals.connect(keystone_service2, glance_config, {'admin_port': 'keystone_admin_port'}) + + # glance + signals.connect(node2, glance_config) + signals.connect(haproxy_keystone_config, glance_config, {'listen_port': 'keystone_port'}) + signals.connect(haproxy_service, glance_config, {'ip': 'keystone_ip'}) + signals.connect(mariadb_service1, glance_config, {'ip': 'mysql_ip'}) + signals.connect(glance_db, glance_config, {'db_name': 'mysql_db'}) + signals.connect(glance_db_user, glance_config, {'new_user_name': 'mysql_user', 'new_user_password': 'mysql_password'}) + signals.connect(node2, glance_api_container) + signals.connect(glance_config, glance_api_container, {'config_dir': 'host_binds'}) + + signals.connect(glance_db_user, glance_api_container, {'new_user_password': 'db_password'}) + signals.connect(glance_keystone_user, glance_api_container, {'user_password': 'keystone_password'}) + signals.connect(glance_keystone_user, glance_api_container, {'admin_token': 'keystone_admin_token'}) + signals.connect(haproxy_config, glance_api_container, {'ip': 'keystone_host'}) + + signals.connect(node2, glance_registry_container) + signals.connect(glance_config, glance_registry_container, {'config_dir': 'host_binds'}) + + signals.connect(mariadb_service1, glance_registry_container, {'ip': 'db_host'}) + signals.connect(glance_db, glance_registry_container, {'db_name': 'db_name', 'login_password': 'db_root_password'}) + signals.connect(glance_db_user, glance_registry_container, {'new_user_name': 'db_user', 'new_user_password': 'db_password'}) + signals.connect(glance_keystone_user, glance_registry_container, {'tenant_name': 'keystone_admin_tenant', 'user_name': 'keystone_user', 'user_password': 'keystone_password'}) + signals.connect(glance_keystone_user, glance_registry_container, {'admin_token': 'keystone_admin_token'}) + signals.connect(haproxy_config, glance_registry_container, {'ip': 'keystone_host'}) + + # glance keystone endpoint + signals.connect(glance_api_container, glance_api_endpoint, {'ip': 'ip', 'ssh_user': 'ssh_user', 'ssh_key': 'ssh_key'}) + signals.connect(keystone_config1, glance_api_endpoint, {'admin_token': 'admin_token'}) + signals.connect(keystone_service1, glance_api_endpoint, {'ip': 'keystone_host', 'admin_port': 'keystone_port'}) + has_errors = False - for r in [node1, - node2, - mariadb_service1, - keystone_db, - rabbitmq_service1, - openstack_vhost, - openstack_rabbitmq_user, - keystone_db_user, - keystone_config1, - keystone_service1, - keystone_config2, - keystone_service2, - haproxy_keystone_config, - haproxy_config, - haproxy_service, - admin_tenant, - admin_user, - admin_role, - keystone_service_endpoint]: + for r in locals().values(): + if not isinstance(r, resource.Resource): + continue + + print 'Validating {}'.format(r.name) errors = validation.validate_resource(r) if errors: has_errors = True @@ -155,12 +206,48 @@ def deploy(): actions.resource_action(admin_role, 'run') actions.resource_action(keystone_service_endpoint, 'run') + actions.resource_action(services_tenant, 'run') + actions.resource_action(glance_keystone_user, 'run') + actions.resource_action(glance_keystone_role, 'run') + actions.resource_action(glance_db, 'run') + actions.resource_action(glance_db_user, 'run') + actions.resource_action(glance_config, 'run') + actions.resource_action(glance_api_container, 'run') + time.sleep(10) #TODO fix + actions.resource_action(glance_registry_container, 'run') + time.sleep(10) + actions.resource_action(glance_api_endpoint, 'run') + # test working configuration requests.get('http://%s:%s' % (keystone_service1.args['ip'].value, keystone_service1.args['port'].value)) requests.get('http://%s:%s' % (keystone_service2.args['ip'].value, keystone_service2.args['port'].value)) requests.get('http://%s:%s' % (haproxy_service.args['ip'].value, haproxy_service.args['ports'].value[0]['value'][0]['value'])) + + token_data = requests.post( + 'http://%s:%s/v2.0/tokens' % (haproxy_service.args['ip'].value, haproxy_keystone_config.args['listen_port'].value), + json.dumps({ + 'auth': { + 'tenantName': glance_keystone_user.args['tenant_name'].value, + 'passwordCredentials': { + 'username': glance_keystone_user.args['user_name'].value, + 'password': glance_keystone_user.args['user_password'].value, + } + } + }), + headers={'Content-Type': 'application/json'} + ) + + token = token_data.json()['access']['token']['id'] + print 'TOKEN: {}'.format(token) + requests.get('http://%s:%s' % (rabbitmq_service1.args['ip'].value, rabbitmq_service1.args['management_port'].value)) + requests.get('http://%s:%s' % (glance_api_container.args['ip'].value, glance_api_container.args['ports'].value[0]['value'][0]['value'])) + requests.get( + 'http://%s:%s' % (glance_registry_container.args['ip'].value, glance_registry_container.args['ports'].value[0]['value'][0]['value']), + headers={'X-Auth-Token': token} + ) + @click.command() def undeploy(): @@ -169,10 +256,21 @@ def undeploy(): resources = map(resource.wrap_resource, db.get_list('resource')) resources = {r.name: r for r in resources} + actions.resource_action(resources['glance_api_endpoint'], 'remove') + actions.resource_action(resources['glance_api_container'], 'remove') + actions.resource_action(resources['glance_registry_container'], 'remove') + actions.resource_action(resources['glance_config'], 'remove') + actions.resource_action(resources['glance_db_user'], 'remove') + actions.resource_action(resources['glance_db'], 'remove') + actions.resource_action(resources['glance_keystone_role'], 'remove') + actions.resource_action(resources['glance_keystone_user'], 'remove') + actions.resource_action(resources['glance_keystone_tenant'], 'remove') + actions.resource_action(resources['keystone_service_endpoint'], 'remove') actions.resource_action(resources['admin_role'], 'remove') actions.resource_action(resources['admin_user'], 'remove') actions.resource_action(resources['admin_tenant'], 'remove') + actions.resource_action(resources['haproxy_service'], 'remove') actions.resource_action(resources['haproxy_config'], 'remove') actions.resource_action(resources['keystone_service2'], 'remove') diff --git a/main.yml b/main.yml index b38cedec..073149f4 100644 --- a/main.yml +++ b/main.yml @@ -13,10 +13,13 @@ - apt: name=python-pudb state=present - apt: name=python-pip state=present - apt: name=python-mysqldb state=present + - apt: name=jq state=present - shell: pip install -U pip - shell: pip install docker-py==1.1.0 - shell: pip install python-keystoneclient==1.5.0 + - shell: pip install httpie + # requirements - shell: pip install -r /vagrant/requirements.txt diff --git a/resources/docker_container/meta.yaml b/resources/docker_container/meta.yaml index 9808149d..76a25600 100644 --- a/resources/docker_container/meta.yaml +++ b/resources/docker_container/meta.yaml @@ -12,10 +12,10 @@ input: schema: [{value: [{value: int}]}] value: [] host_binds: - schema: [{value: {src: str, dst: str}}] + schema: [{value: {src: str, dst: str, mode: str}}] value: [] volume_binds: - schema: [{src: str, dst: str}] + schema: [{src: str, dst: str, mode: str}] value: [] ssh_user: schema: str! diff --git a/resources/glance_api_service/actions/remove.yml b/resources/glance_api_service/actions/remove.yml new file mode 100644 index 00000000..d3c3149f --- /dev/null +++ b/resources/glance_api_service/actions/remove.yml @@ -0,0 +1,6 @@ + +- hosts: [{{ ip }}] + sudo: yes + tasks: + - shell: docker stop {{ name }} + - shell: docker rm {{ name }} diff --git a/resources/glance_api_service/actions/run.yml b/resources/glance_api_service/actions/run.yml new file mode 100644 index 00000000..567748b0 --- /dev/null +++ b/resources/glance_api_service/actions/run.yml @@ -0,0 +1,28 @@ + +- hosts: [{{ ip }}] + sudo: yes + tasks: + - docker: + command: /bin/bash -c "glance-manage db_sync && /usr/bin/glance-api" + name: {{ name }} + image: {{ image }} + state: running + net: host + {% if ports.value %} + ports: + {% for port in ports.value %} + {% for p in port['value'] %} + - {{ p['value'] }}:{{ p['value'] }} + {% endfor %} + {% endfor %} + {% endif %} + {% if host_binds.value %} + volumes: + # TODO: host_binds might need more work + # Currently it's not that trivial to pass custom src: dst here + # (when a config variable is passed here from other resource) + # so we mount it to the same directory as on host + {% for bind in host_binds.value %} + - {{ bind['value']['src'] }}:{{ bind['value']['dst'] }}:{{ bind['value'].get('mode', 'ro') }} + {% endfor %} + {% endif %} diff --git a/resources/glance_api_service/meta.yaml b/resources/glance_api_service/meta.yaml new file mode 100644 index 00000000..f1f06b6c --- /dev/null +++ b/resources/glance_api_service/meta.yaml @@ -0,0 +1,40 @@ +id: container +handler: ansible +version: 1.0.0 +input: + ip: + schema: str! + value: + image: + schema: str! + value: + ports: + schema: [{value: [{value: int}]}] + value: [] + host_binds: + schema: [{value: {src: str, dst: str, mode: str}}] + value: [] + volume_binds: + schema: [{src: str, dst: str, mode: str}] + value: [] + ssh_user: + schema: str! + value: [] + ssh_key: + schema: str! + value: [] + + db_password: + schema: str! + value: + keystone_admin_token: + schema: str! + value: + keystone_password: + schema: str! + value: + keystone_host: + schema: str! + value: + +tags: [resource/container] diff --git a/resources/glance_config/actions/remove.yml b/resources/glance_config/actions/remove.yml new file mode 100644 index 00000000..a0a79ad4 --- /dev/null +++ b/resources/glance_config/actions/remove.yml @@ -0,0 +1,5 @@ + +- hosts: [{{ ip }}] + sudo: yes + tasks: + - shell: echo 'removed' diff --git a/resources/glance_config/actions/run.yml b/resources/glance_config/actions/run.yml new file mode 100644 index 00000000..b1195753 --- /dev/null +++ b/resources/glance_config/actions/run.yml @@ -0,0 +1,36 @@ +- hosts: [{{ ip }}] + sudo: yes + vars: + api_port: {{ api_port }} + registry_port: {{ registry_port }} + keystone_ip: {{ keystone_ip }} + keystone_port: {{ keystone_port }} + keystone_admin_user: {{ keystone_admin_user }} + keystone_admin_password: {{ keystone_admin_password }} + keystone_admin_port: {{ keystone_admin_port }} + keystone_admin_tenant: {{ keystone_admin_tenant }} + mysql_ip: {{ mysql_ip }} + mysql_db: {{ mysql_db }} + mysql_user: {{ mysql_user }} + mysql_password: {{ mysql_password }} + config_dir: {src: {{ config_dir.value['src'] }}, dst: {{ config_dir.value['dst'] }}} + tasks: + - file: path={{ config_dir.value['src'] }}/ state=directory + - file: path={{ config_dir.value['src'] }}/glance-api.conf state=touch + - file: path={{ config_dir.value['src'] }}/glance-api-paste.ini state=touch + - file: path={{ config_dir.value['src'] }}/glance-cache.conf state=touch + - file: path={{ config_dir.value['src'] }}/glance-registry.conf state=touch + - file: path={{ config_dir.value['src'] }}/glance-registry-paste.ini state=touch + - file: path={{ config_dir.value['src'] }}/glance-scrubber.conf state=touch + - file: path={{ config_dir.value['src'] }}/policy.json state=touch + - file: path={{ config_dir.value['src'] }}/schema-image.json state=touch + - file: path={{ config_dir.value['src'] }}/exports state=touch + - template: src={{ resource_dir }}/templates/glance-api.conf dest={{ config_dir.value['src'] }}/glance-api.conf + - template: src={{ resource_dir }}/templates/glance-api-paste.ini dest={{ config_dir.value['src'] }}/glance-api-paste.ini + - template: src={{ resource_dir }}/templates/glance-cache.conf dest={{ config_dir.value['src'] }}/glance-cache.conf + - template: src={{ resource_dir }}/templates/glance-registry.conf dest={{ config_dir.value['src'] }}/glance-registry.conf + - template: src={{ resource_dir }}/templates/glance-registry-paste.ini dest={{ config_dir.value['src'] }}/glance-registry-paste.ini + - template: src={{ resource_dir }}/templates/glance-scrubber.conf dest={{ config_dir.value['src'] }}/glance-scrubber.conf + - template: src={{ resource_dir }}/templates/policy.json dest={{ config_dir.value['src'] }}/policy.json + - template: src={{ resource_dir }}/templates/schema-image.json dest={{ config_dir.value['src'] }}/schema-image.json + - template: src={{ resource_dir }}/templates/exports dest={{ config_dir.value['src'] }}/glance-export diff --git a/resources/glance_config/meta.yaml b/resources/glance_config/meta.yaml new file mode 100644 index 00000000..d2a4c94e --- /dev/null +++ b/resources/glance_config/meta.yaml @@ -0,0 +1,53 @@ +id: glance_config +handler: ansible +version: 1.0.0 +input: + ip: + schema: str! + value: + ssh_user: + schema: str! + value: [] + ssh_key: + schema: str! + value: [] + + config_dir: + schema: {src: str!, dst: str!, mode: str} + value: {src: /etc/solar/glance, dst: /etc/glance, mode: rw} + api_port: + schema: int! + value: 9292 + registry_port: + schema: int! + value: 9191 + keystone_ip: + schema: str! + value: + keystone_port: + schema: int! + value: 5000 + keystone_admin_user: + schema: str! + value: glance_admin + keystone_admin_password: + schema: str! + value: password1234 + keystone_admin_port: + schema: int! + value: + keystone_admin_tenant: + schema: str! + value: service_admins + mysql_ip: + schema: str! + value: + mysql_db: + schema: str! + value: + mysql_user: + schema: str! + value: + mysql_password: + schema: str! + value: diff --git a/resources/glance_config/templates/exports b/resources/glance_config/templates/exports new file mode 100644 index 00000000..d9d35bc8 --- /dev/null +++ b/resources/glance_config/templates/exports @@ -0,0 +1,4 @@ +export OS_TENANT_NAME={{ keystone_admin_tenant }} +export OS_USERNAME={{ keystone_admin_user }} +export OS_PASSWORD={{ keystone_admin_password }} +export OS_AUTH_URL=http://{{ keystone_ip }}:{{ keystone_admin_port }}/v2.0 \ No newline at end of file diff --git a/resources/glance_config/templates/glance-api-paste.ini b/resources/glance_config/templates/glance-api-paste.ini new file mode 100644 index 00000000..03667961 --- /dev/null +++ b/resources/glance_config/templates/glance-api-paste.ini @@ -0,0 +1,82 @@ +# Use this pipeline for no auth or image caching - DEFAULT +[pipeline:glance-api] +#pipeline = versionnegotiation osprofiler unauthenticated-context rootapp +pipeline = versionnegotiation authtoken context appv1app + +# Use this pipeline for image caching and no auth +[pipeline:glance-api-caching] +pipeline = versionnegotiation osprofiler unauthenticated-context cache rootapp + +# Use this pipeline for caching w/ management interface but no auth +[pipeline:glance-api-cachemanagement] +pipeline = versionnegotiation osprofiler unauthenticated-context cache cachemanage rootapp + +# Use this pipeline for keystone auth +[pipeline:glance-api-keystone] +pipeline = versionnegotiation osprofiler authtoken context rootapp + +# Use this pipeline for keystone auth with image caching +[pipeline:glance-api-keystone+caching] +pipeline = versionnegotiation osprofiler authtoken context cache rootapp + +# Use this pipeline for keystone auth with caching and cache management +[pipeline:glance-api-keystone+cachemanagement] +pipeline = versionnegotiation osprofiler authtoken context cache cachemanage rootapp + +# Use this pipeline for authZ only. This means that the registry will treat a +# user as authenticated without making requests to keystone to reauthenticate +# the user. +[pipeline:glance-api-trusted-auth] +pipeline = versionnegotiation osprofiler context rootapp + +# Use this pipeline for authZ only. This means that the registry will treat a +# user as authenticated without making requests to keystone to reauthenticate +# the user and uses cache management +[pipeline:glance-api-trusted-auth+cachemanagement] +pipeline = versionnegotiation osprofiler context cache cachemanage rootapp + +[composite:rootapp] +paste.composite_factory = glance.api:root_app_factory +/: apiversions +/v1: apiv1app +/v2: apiv2app + +[app:apiversions] +paste.app_factory = glance.api.versions:create_resource + +[app:apiv1app] +paste.app_factory = glance.api.v1.router:API.factory + +[app:apiv2app] +paste.app_factory = glance.api.v2.router:API.factory + +[filter:versionnegotiation] +paste.filter_factory = glance.api.middleware.version_negotiation:VersionNegotiationFilter.factory + +[filter:cache] +paste.filter_factory = glance.api.middleware.cache:CacheFilter.factory + +[filter:cachemanage] +paste.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter.factory + +[filter:context] +paste.filter_factory = glance.api.middleware.context:ContextMiddleware.factory + +[filter:unauthenticated-context] +paste.filter_factory = glance.api.middleware.context:UnauthenticatedContextMiddleware.factory + +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory +identity_uri = http://{{ keystone_ip }}:{{ keystone_admin_port }} +admin_user = {{ keystone_admin_user }} +admin_tenant_name = {{ keystone_admin_tenant }} +admin_password = {{ keystone_admin_password }} +#delay_auth_decision = true + +[filter:gzip] +paste.filter_factory = glance.api.middleware.gzip:GzipMiddleware.factory + +[filter:osprofiler] +paste.filter_factory = osprofiler.web:WsgiMiddleware.factory +hmac_keys = SECRET_KEY +enabled = yes diff --git a/resources/glance_config/templates/glance-api.conf b/resources/glance_config/templates/glance-api.conf new file mode 100644 index 00000000..9e379fb4 --- /dev/null +++ b/resources/glance_config/templates/glance-api.conf @@ -0,0 +1,35 @@ +[DEFAULT] +default_store = file +bind_host = 0.0.0.0 +bind_port = {{ api_port }} +log_file = /var/log/glance/api.log +backlog = 4096 +registry_host = 0.0.0.0 +registry_port = {{ registry_port }} +registry_client_protocol = http + +delayed_delete = False +scrub_time = 43200 +scrubber_datadir = /var/lib/glance/scrubber +image_cache_dir = /var/lib/glance/image-cache/ + +[database] +connection = mysql://{{ mysql_user }}:{{ mysql_password }}@{{ mysql_ip }}/{{ mysql_db }} +backend = mysql + +[keystone_authtoken] +auth_uri = http://{{ keystone_ip }}:{{ keystone_port }}/v2.0 +identity_uri = http://{{ keystone_ip }}:{{ keystone_admin_port }} +admin_tenant_name = {{ keystone_admin_tenant }} +admin_user = {{ keystone_admin_user }} +admin_password = {{ keystone_admin_password }} +revocation_cache_time = 10 + +[paste_deploy] +flavor=keystone+cachemanagement + +[glance_store] +filesystem_store_datadir = /var/lib/glance/images/ +sheepdog_store_address = localhost +sheepdog_store_port = 7000 +sheepdog_store_chunk_size = 64 diff --git a/resources/glance_config/templates/glance-cache.conf b/resources/glance_config/templates/glance-cache.conf new file mode 100644 index 00000000..0246b672 --- /dev/null +++ b/resources/glance_config/templates/glance-cache.conf @@ -0,0 +1,200 @@ +[DEFAULT] +# Show more verbose log output (sets INFO log level output) +#verbose = False + +# Show debugging output in logs (sets DEBUG log level output) +#debug = False + +# Log to this file. Make sure you do not set the same log file for both the API +# and registry servers! +# +# If `log_file` is omitted and `use_syslog` is false, then log messages are +# sent to stdout as a fallback. +log_file = /var/log/glance/image-cache.log + +# Send logs to syslog (/dev/log) instead of to file specified by `log_file` +#use_syslog = False + +# Directory that the Image Cache writes data to +image_cache_dir = /var/lib/glance/image-cache/ + +# Number of seconds after which we should consider an incomplete image to be +# stalled and eligible for reaping +image_cache_stall_time = 86400 + +# Max cache size in bytes +image_cache_max_size = 10737418240 + +# Address to find the registry server +registry_host = 0.0.0.0 + +# Port the registry server is listening on +registry_port = 9191 + +# Auth settings if using Keystone +# auth_url = http://127.0.0.1:5000/v2.0/ +# admin_tenant_name = %SERVICE_TENANT_NAME% +# admin_user = %SERVICE_USER% +# admin_password = %SERVICE_PASSWORD% + +# List of which store classes and store class locations are +# currently known to glance at startup. +# known_stores = glance.store.filesystem.Store, +# glance.store.http.Store, +# glance.store.rbd.Store, +# glance.store.s3.Store, +# glance.store.swift.Store, +# glance.store.sheepdog.Store, +# glance.store.cinder.Store, +# glance.store.vmware_datastore.Store, + +# ============ Filesystem Store Options ======================== + +# Directory that the Filesystem backend store +# writes image data to +filesystem_store_datadir = /var/lib/glance/images/ + +# ============ Swift Store Options ============================= + +# Version of the authentication service to use +# Valid versions are '2' for keystone and '1' for swauth and rackspace +swift_store_auth_version = 2 + +# Address where the Swift authentication service lives +# Valid schemes are 'http://' and 'https://' +# If no scheme specified, default to 'https://' +# For swauth, use something like '127.0.0.1:8080/v1.0/' +swift_store_auth_address = 127.0.0.1:5000/v2.0/ + +# User to authenticate against the Swift authentication service +# If you use Swift authentication service, set it to 'account':'user' +# where 'account' is a Swift storage account and 'user' +# is a user in that account +swift_store_user = jdoe:jdoe + +# Auth key for the user authenticating against the +# Swift authentication service +swift_store_key = a86850deb2742ec3cb41518e26aa2d89 + +# Container within the account that the account should use +# for storing images in Swift +swift_store_container = glance + +# Do we create the container if it does not exist? +swift_store_create_container_on_put = False + +# What size, in MB, should Glance start chunking image files +# and do a large object manifest in Swift? By default, this is +# the maximum object size in Swift, which is 5GB +swift_store_large_object_size = 5120 + +# When doing a large object manifest, what size, in MB, should +# Glance write chunks to Swift? This amount of data is written +# to a temporary disk buffer during the process of chunking +# the image file, and the default is 200MB +swift_store_large_object_chunk_size = 200 + +# Whether to use ServiceNET to communicate with the Swift storage servers. +# (If you aren't RACKSPACE, leave this False!) +# +# To use ServiceNET for authentication, prefix hostname of +# `swift_store_auth_address` with 'snet-'. +# Ex. https://example.com/v1.0/ -> https://snet-example.com/v1.0/ +swift_enable_snet = False + +# ============ S3 Store Options ============================= + +# Address where the S3 authentication service lives +# Valid schemes are 'http://' and 'https://' +# If no scheme specified, default to 'http://' +s3_store_host = 127.0.0.1:8080/v1.0/ + +# User to authenticate against the S3 authentication service +s3_store_access_key = <20-char AWS access key> + +# Auth key for the user authenticating against the +# S3 authentication service +s3_store_secret_key = <40-char AWS secret key> + +# Container within the account that the account should use +# for storing images in S3. Note that S3 has a flat namespace, +# so you need a unique bucket name for your glance images. An +# easy way to do this is append your AWS access key to "glance". +# S3 buckets in AWS *must* be lowercased, so remember to lowercase +# your AWS access key if you use it in your bucket name below! +s3_store_bucket = glance + +# Do we create the bucket if it does not exist? +s3_store_create_bucket_on_put = False + +# When sending images to S3, the data will first be written to a +# temporary buffer on disk. By default the platform's temporary directory +# will be used. If required, an alternative directory can be specified here. +# s3_store_object_buffer_dir = /path/to/dir + +# ============ Cinder Store Options =========================== + +# Info to match when looking for cinder in the service catalog +# Format is : separated values of the form: +# :: (string value) +#cinder_catalog_info = volume:cinder:publicURL + +# Override service catalog lookup with template for cinder endpoint +# e.g. http://localhost:8776/v1/%(project_id)s (string value) +#cinder_endpoint_template = + +# Region name of this node (string value) +#os_region_name = + +# Location of ca certicates file to use for cinder client requests +# (string value) +#cinder_ca_certificates_file = + +# Number of cinderclient retries on failed http calls (integer value) +#cinder_http_retries = 3 + +# Allow to perform insecure SSL requests to cinder (boolean value) +#cinder_api_insecure = False + +# ============ VMware Datastore Store Options ===================== + +# ESX/ESXi or vCenter Server target system. +# The server value can be an IP address or a DNS name +# e.g. 127.0.0.1, 127.0.0.1:443, www.vmware-infra.com +#vmware_server_host = + +# Server username (string value) +#vmware_server_username = + +# Server password (string value) +#vmware_server_password = + +# Inventory path to a datacenter (string value) +# Value optional when vmware_server_ip is an ESX/ESXi host: if specified +# should be `ha-datacenter`. +#vmware_datacenter_path = + +# Datastore associated with the datacenter (string value) +#vmware_datastore_name = + +# The number of times we retry on failures +# e.g., socket error, etc (integer value) +#vmware_api_retry_count = 10 + +# The interval used for polling remote tasks +# invoked on VMware ESX/VC server in seconds (integer value) +#vmware_task_poll_interval = 5 + +# Absolute path of the folder containing the images in the datastore +# (string value) +#vmware_store_image_dir = /openstack_glance + +# Allow to perform insecure SSL requests to the target system (boolean value) +#vmware_api_insecure = False + +# ================= Security Options ========================== + +# AES key for encrypting store 'location' metadata, including +# -- if used -- Swift or S3 credentials +# Should be set to a random string of length 16, 24 or 32 bytes +# metadata_encryption_key = <16, 24 or 32 char registry metadata key> diff --git a/resources/glance_config/templates/glance-registry-paste.ini b/resources/glance_config/templates/glance-registry-paste.ini new file mode 100644 index 00000000..01994804 --- /dev/null +++ b/resources/glance_config/templates/glance-registry-paste.ini @@ -0,0 +1,35 @@ +# Use this pipeline for no auth - DEFAULT +[pipeline:glance-registry] +#pipeline = osprofiler unauthenticated-context registryapp +pipeline = authtoke context registryapp + +# Use this pipeline for keystone auth +[pipeline:glance-registry-keystone] +pipeline = osprofiler authtoken context registryapp + +# Use this pipeline for authZ only. This means that the registry will treat a +# user as authenticated without making requests to keystone to reauthenticate +# the user. +[pipeline:glance-registry-trusted-auth] +pipeline = osprofiler context registryapp + +[app:registryapp] +paste.app_factory = glance.registry.api:API.factory + +[filter:context] +paste.filter_factory = glance.api.middleware.context:ContextMiddleware.factory + +[filter:unauthenticated-context] +paste.filter_factory = glance.api.middleware.context:UnauthenticatedContextMiddleware.factory + +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory +identity_uri = http://{{ keystone_ip }}:{{ keystone_admin_port }} +admin_user = {{ keystone_admin_user }} +admin_tenant_name = {{ keystone_admin_tenant }} +admin_password = {{ keystone_admin_password }} + +[filter:osprofiler] +paste.filter_factory = osprofiler.web:WsgiMiddleware.factory +hmac_keys = SECRET_KEY +enabled = yes diff --git a/resources/glance_config/templates/glance-registry.conf b/resources/glance_config/templates/glance-registry.conf new file mode 100644 index 00000000..7efe994a --- /dev/null +++ b/resources/glance_config/templates/glance-registry.conf @@ -0,0 +1,22 @@ +[DEFAULT] +bind_host = 0.0.0.0 +bind_port = 9191 +log_file = /var/log/glance/registry.log +backlog = 4096 +api_limit_max = 1000 +limit_param_default = 25 + +[database] +backend = mysql +connection = mysql://{{ mysql_user }}:{{ mysql_password }}@{{ mysql_ip }}/{{ mysql_db }} + +[keystone_authtoken] +auth_uri = http://{{ keystone_ip }}:{{ keystone_port }}/v2.0 +identity_uri = http://{{ keystone_ip }}:{{ keystone_admin_port }} +admin_tenant_name = {{ keystone_admin_tenant }} +admin_user = {{ keystone_admin_user }} +admin_password = {{ keystone_admin_password }} + +[paste_deploy] +flavor=keystone +[profiler] diff --git a/resources/glance_config/templates/glance-scrubber.conf b/resources/glance_config/templates/glance-scrubber.conf new file mode 100644 index 00000000..ecfc7bff --- /dev/null +++ b/resources/glance_config/templates/glance-scrubber.conf @@ -0,0 +1,108 @@ +[DEFAULT] +# Show more verbose log output (sets INFO log level output) +#verbose = False + +# Show debugging output in logs (sets DEBUG log level output) +#debug = False + +# Log to this file. Make sure you do not set the same log file for both the API +# and registry servers! +# +# If `log_file` is omitted and `use_syslog` is false, then log messages are +# sent to stdout as a fallback. +log_file = /var/log/glance/scrubber.log + +# Send logs to syslog (/dev/log) instead of to file specified by `log_file` +#use_syslog = False + +# Should we run our own loop or rely on cron/scheduler to run us +daemon = False + +# Loop time between checking for new items to schedule for delete +wakeup_time = 300 + +# Directory that the scrubber will use to remind itself of what to delete +# Make sure this is also set in glance-api.conf +scrubber_datadir = /var/lib/glance/scrubber + +# Only one server in your deployment should be designated the cleanup host +cleanup_scrubber = False + +# pending_delete items older than this time are candidates for cleanup +cleanup_scrubber_time = 86400 + +# Address to find the registry server for cleanups +registry_host = 0.0.0.0 + +# Port the registry server is listening on +registry_port = 9191 + +# Auth settings if using Keystone +# auth_url = http://127.0.0.1:5000/v2.0/ +# admin_tenant_name = %SERVICE_TENANT_NAME% +# admin_user = %SERVICE_USER% +# admin_password = %SERVICE_PASSWORD% + +# Directory to use for lock files. Default to a temp directory +# (string value). This setting needs to be the same for both +# glance-scrubber and glance-api. +#lock_path= + +# API to use for accessing data. Default value points to sqlalchemy +# package, it is also possible to use: glance.db.registry.api +#data_api = glance.db.sqlalchemy.api + +# ================= Security Options ========================== + +# AES key for encrypting store 'location' metadata, including +# -- if used -- Swift or S3 credentials +# Should be set to a random string of length 16, 24 or 32 bytes +#metadata_encryption_key = <16, 24 or 32 char registry metadata key> + +# ================= Database Options ===============+========== + +[database] + +# The SQLAlchemy connection string used to connect to the +# database (string value) +#connection=sqlite:////glance/openstack/common/db/$sqlite_db + +# The SQLAlchemy connection string used to connect to the +# slave database (string value) +#slave_connection= + +# timeout before idle sql connections are reaped (integer +# value) +#idle_timeout=3600 + +# Minimum number of SQL connections to keep open in a pool +# (integer value) +#min_pool_size=1 + +# Maximum number of SQL connections to keep open in a pool +# (integer value) +#max_pool_size= + +# maximum db connection retries during startup. (setting -1 +# implies an infinite retry count) (integer value) +#max_retries=10 + +# interval between retries of opening a sql connection +# (integer value) +#retry_interval=10 + +# If set, use this value for max_overflow with sqlalchemy +# (integer value) +#max_overflow= + +# Verbosity of SQL debugging information. 0=None, +# 100=Everything (integer value) +#connection_debug=0 + +# Add python stack traces to SQL as comment strings (boolean +# value) +#connection_trace=false + +# If set, use this value for pool_timeout with sqlalchemy +# (integer value) +#pool_timeout= diff --git a/resources/glance_config/templates/policy.json b/resources/glance_config/templates/policy.json new file mode 100644 index 00000000..325f00b2 --- /dev/null +++ b/resources/glance_config/templates/policy.json @@ -0,0 +1,52 @@ +{ + "context_is_admin": "role:admin", + "default": "", + + "add_image": "", + "delete_image": "", + "get_image": "", + "get_images": "", + "modify_image": "", + "publicize_image": "role:admin", + "copy_from": "", + + "download_image": "", + "upload_image": "", + + "delete_image_location": "", + "get_image_location": "", + "set_image_location": "", + + "add_member": "", + "delete_member": "", + "get_member": "", + "get_members": "", + "modify_member": "", + + "manage_image_cache": "role:admin", + + "get_task": "", + "get_tasks": "", + "add_task": "", + "modify_task": "", + + "get_metadef_namespace": "", + "get_metadef_namespaces":"", + "modify_metadef_namespace":"", + "add_metadef_namespace":"", + + "get_metadef_object":"", + "get_metadef_objects":"", + "modify_metadef_object":"", + "add_metadef_object":"", + + "list_metadef_resource_types":"", + "get_metadef_resource_type":"", + "add_metadef_resource_type_association":"", + + "get_metadef_property":"", + "get_metadef_properties":"", + "modify_metadef_property":"", + "add_metadef_property":"" + +} diff --git a/resources/glance_config/templates/schema-image.json b/resources/glance_config/templates/schema-image.json new file mode 100644 index 00000000..5aafd6b3 --- /dev/null +++ b/resources/glance_config/templates/schema-image.json @@ -0,0 +1,28 @@ +{ + "kernel_id": { + "type": "string", + "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", + "description": "ID of image stored in Glance that should be used as the kernel when booting an AMI-style image." + }, + "ramdisk_id": { + "type": "string", + "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", + "description": "ID of image stored in Glance that should be used as the ramdisk when booting an AMI-style image." + }, + "instance_uuid": { + "type": "string", + "description": "ID of instance used to create this image." + }, + "architecture": { + "description": "Operating system architecture as specified in http://docs.openstack.org/trunk/openstack-compute/admin/content/adding-images.html", + "type": "string" + }, + "os_distro": { + "description": "Common name of operating system distribution as specified in http://docs.openstack.org/trunk/openstack-compute/admin/content/adding-images.html", + "type": "string" + }, + "os_version": { + "description": "Operating system version as specified by the distributor", + "type": "string" + } +} diff --git a/resources/glance_registry_service/actions/remove.yml b/resources/glance_registry_service/actions/remove.yml new file mode 100644 index 00000000..d3c3149f --- /dev/null +++ b/resources/glance_registry_service/actions/remove.yml @@ -0,0 +1,6 @@ + +- hosts: [{{ ip }}] + sudo: yes + tasks: + - shell: docker stop {{ name }} + - shell: docker rm {{ name }} diff --git a/resources/glance_registry_service/actions/run.yml b/resources/glance_registry_service/actions/run.yml new file mode 100644 index 00000000..51b208b6 --- /dev/null +++ b/resources/glance_registry_service/actions/run.yml @@ -0,0 +1,29 @@ + +- hosts: [{{ ip }}] + sudo: yes + tasks: + - docker: + #command: /bin/bash -c "glance-manage db_sync && /usr/bin/glance-registry" + command: /usr/bin/glance-registry + name: {{ name }} + image: {{ image }} + state: running + net: host + {% if ports.value %} + ports: + {% for port in ports.value %} + {% for p in port['value'] %} + - {{ p['value'] }}:{{ p['value'] }} + {% endfor %} + {% endfor %} + {% endif %} + {% if host_binds.value %} + volumes: + # TODO: host_binds might need more work + # Currently it's not that trivial to pass custom src: dst here + # (when a config variable is passed here from other resource) + # so we mount it to the same directory as on host + {% for bind in host_binds.value %} + - {{ bind['value']['src'] }}:{{ bind['value']['dst'] }}:{{ bind['value'].get('mode', 'ro') }} + {% endfor %} + {% endif %} diff --git a/resources/glance_registry_service/meta.yaml b/resources/glance_registry_service/meta.yaml new file mode 100644 index 00000000..41734322 --- /dev/null +++ b/resources/glance_registry_service/meta.yaml @@ -0,0 +1,58 @@ +id: container +handler: ansible +version: 1.0.0 +input: + ip: + schema: str! + value: + image: + schema: str! + value: + ports: + schema: [{value: [{value: int}]}] + value: [] + host_binds: + schema: [{value: {src: str, dst: str, mode: str}}] + value: [] + volume_binds: + schema: [{src: str, dst: str, mode: str}] + value: [] + ssh_user: + schema: str! + value: [] + ssh_key: + schema: str! + value: [] + + db_host: + schema: str! + value: + db_root_password: + schema: str! + value: + db_name: + schema: str! + value: + db_password: + schema: str! + value: + db_user: + schema: str! + value: + keystone_admin_token: + schema: str! + value: + keystone_admin_tenant: + schema: str! + value: + keystone_user: + schema: str! + value: + keystone_password: + schema: str! + value: + keystone_host: + schema: str! + value: + +tags: [resource/container] diff --git a/resources/keystone_config/actions/run.yml b/resources/keystone_config/actions/run.yml index e24d0fae..ad457c53 100644 --- a/resources/keystone_config/actions/run.yml +++ b/resources/keystone_config/actions/run.yml @@ -2,6 +2,8 @@ sudo: yes vars: admin_token: {{admin_token}} + keystone_host: {{ ip }} + keystone_port: {{ port }} db_user: {{db_user}} db_password: {{db_password}} db_host: {{db_host}} @@ -12,3 +14,4 @@ - template: src={{resource_dir}}/templates/default_catalog.templates dest={{config_dir}}/default_catalog.templates - template: src={{resource_dir}}/templates/logging.conf dest={{config_dir}}/logging.conf - template: src={{resource_dir}}/templates/policy.json dest={{config_dir}}/policy.json + - template: src={{resource_dir}}/templates/exports dest={{ config_dir }}/keystone-exports diff --git a/resources/keystone_config/templates/exports b/resources/keystone_config/templates/exports new file mode 100644 index 00000000..cc3a1c1c --- /dev/null +++ b/resources/keystone_config/templates/exports @@ -0,0 +1,2 @@ +export OS_SERVICE_ENDPOINT=http://localhost:35357/v2.0/ +export OS_SERVICE_TOKEN={{ admin_token }} diff --git a/resources/keystone_role/actions/run.yml b/resources/keystone_role/actions/run.yml index 88960081..4d3df76c 100644 --- a/resources/keystone_role/actions/run.yml +++ b/resources/keystone_role/actions/run.yml @@ -1,5 +1,7 @@ - hosts: [{{ ip }}] sudo: yes tasks: + - name: install python-keystoneclient + shell: pip install python-keystoneclient - name: keystone role keystone_user: endpoint=http://{{keystone_host}}:{{keystone_port}}/v2.0/ token={{admin_token}} user={{user_name}} tenant={{tenant_name}} role={{role_name}} state=present diff --git a/resources/keystone_tenant/actions/run.yml b/resources/keystone_tenant/actions/run.yml index 5122a7d8..1cf2597f 100644 --- a/resources/keystone_tenant/actions/run.yml +++ b/resources/keystone_tenant/actions/run.yml @@ -1,5 +1,7 @@ - hosts: [{{ ip }}] sudo: yes tasks: + - name: install python-keystoneclient + shell: pip install python-keystoneclient - name: keystone tenant keystone_user: endpoint=http://{{keystone_host}}:{{keystone_port}}/v2.0/ token={{admin_token}} tenant={{tenant_name}} state=present diff --git a/resources/keystone_user/actions/run.yml b/resources/keystone_user/actions/run.yml index 113d01b1..eb3c3743 100644 --- a/resources/keystone_user/actions/run.yml +++ b/resources/keystone_user/actions/run.yml @@ -1,5 +1,7 @@ - hosts: [{{ ip }}] sudo: yes tasks: + - name: install python-keystoneclient + shell: pip install python-keystoneclient - name: keystone user - keystone_user: endpoint=http://{{keystone_host}}:{{keystone_port}}/v2.0/ token={{admin_token}} user={{user_name}} password={{user_password}} tenant={{tenant_name}} state=present + keystone_user: endpoint=http://{{ keystone_host }}:{{ keystone_port }}/v2.0/ token={{ admin_token }} user={{ user_name }} password={{ user_password }} tenant={{ tenant_name }} state=present diff --git a/resources/mariadb_service/actions/run.yml b/resources/mariadb_service/actions/run.yml index b1e9d87f..08fa7cd1 100644 --- a/resources/mariadb_service/actions/run.yml +++ b/resources/mariadb_service/actions/run.yml @@ -9,4 +9,9 @@ ports: - {{ port }}:3306 env: - MYSQL_ROOT_PASSWORD: {{ root_password }} + MYSQL_ROOT_PASSWORD: {{ root_password }} + - shell: docker exec -t {{ name }} mysql -p{{ root_password }} -uroot -e "select 1" + register: result + until: result.rc == 0 + retries: 20 + delay: 0.5 diff --git a/solar/solar/core/handlers/ansible.py b/solar/solar/core/handlers/ansible.py index 9bc74741..0789c598 100644 --- a/solar/solar/core/handlers/ansible.py +++ b/solar/solar/core/handlers/ansible.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import os import subprocess -import yaml from solar.core.handlers.base import BaseHandler @@ -14,7 +13,11 @@ class Ansible(BaseHandler): print 'playbook_file', playbook_file call_args = ['ansible-playbook', '--module-path', '/vagrant/library', '-i', inventory_file, playbook_file] print 'EXECUTING: ', ' '.join(call_args) - subprocess.call(call_args) + try: + subprocess.check_output(call_args) + except subprocess.CalledProcessError as e: + print e.output + raise #def _get_connection(self, resource): # return {'ssh_user': '',