Add Ironic

This change introduces services required for Ironic support.

Change-Id: Ic21d6379450471d91b2d7681911ca8b36c3fb0bf
This commit is contained in:
Andrey Shestakov 2016-09-27 18:56:06 +03:00
parent f5b1c89410
commit 0b5a36f970
18 changed files with 480 additions and 0 deletions

69
.gitignore vendored Normal file
View File

@ -0,0 +1,69 @@
*.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
dist
build
.eggs
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
cover
.tox
nosetests.xml
.testrepository
.venv
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
# oslo-config-generator
etc/*.sample
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*.swp
.*sw?
# Vagrant
.vagrant
vagrant/Vagrantfile.custom
vagrant/vagrantkey*
# generated openrc
openrc
# tests
tests/.cache/*

View File

@ -0,0 +1,8 @@
FROM {{ image_spec("ironic-base") }}
MAINTAINER {{ maintainer }}
RUN apt-get install -y --no-install-recommends \
mysql-client \
&& apt-get clean
USER ironic

View File

@ -0,0 +1,15 @@
FROM {{ image_spec("openstack-base") }}
MAINTAINER {{ maintainer }}
{{ copy_sources("openstack/ironic", "/ironic") }}
{{ copy_sources("openstack/ironic-staging-drivers", "/ironic-staging-drivers") }}
RUN useradd -U -m -d /home/ironic -G microservices ironic \
&& /var/lib/microservices/venv/bin/pip install --upgrade -c /ironic/requirements.txt /ironic \
&& /var/lib/microservices/venv/bin/pip install --upgrade -r /ironic-staging-drivers/ironic_staging_drivers/ansible/python-requirements.txt \
&& /var/lib/microservices/venv/bin/pip install --upgrade -c /ironic-staging-drivers/requirements.txt /ironic-staging-drivers \
&& mkdir -p /etc/ironic /etc/ironic/keys /var/lib/ironic /home/ironic/.ssh /var/log/ironic \
&& cp -r /ironic/etc/ironic/* /etc/ironic/ \
&& chown -R ironic: /etc/ironic /var/lib/ironic /var/log/ironic /home/ironic \
&& chmod -R 700 /home/ironic \
&& rm -rf /ironic /ironic-staging-drivers

View File

@ -0,0 +1,11 @@
FROM {{ image_spec("ironic-base") }}
MAINTAINER {{ maintainer }}
RUN apt-get install -y --no-install-recommends \
qemu-utils \
ipmitool \
socat \
openssh-client \
&& apt-get clean
USER ironic

View File

@ -0,0 +1,12 @@
FROM {{ image_spec("ironic-base") }}
MAINTAINER {{ maintainer }}
RUN apt-get install -y --no-install-recommends \
nginx-light \
&& apt-get clean \
&& rm /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default \
&& chown -R ironic: /etc/nginx /var/lib/nginx /var/log/nginx
RUN chmod 777 /run
USER ironic

View File

@ -0,0 +1,14 @@
FROM {{ image_spec("ironic-base") }}
MAINTAINER {{ maintainer }}
RUN apt-get install -y --no-install-recommends \
tftpd-hpa \
syslinux-common \
syslinux \
pxelinux \
ipxe \
&& apt-get clean
COPY tftp-map-file /map-file
USER root

View File

@ -0,0 +1,2 @@
r ^([^/]) /var/lib/ironic/tftpboot/\1
r ^(/tftpboot/) /var/lib/ironic/tftpboot/\2

View File

@ -0,0 +1,37 @@
configs:
ironic:
api_port:
cont: 6385
ingress: ironic
username: ironic
password: password
db:
username: ironic
password: password
name: ironic
logging_debug: false
automated_clean: false
enabled_drivers: "fake,pxe_ssh_ansible,pxe_ipmitool_ansible"
swift:
temp_url_key: password
ipxe:
external_port: 6388
use_swift: false
ssh_key: false
ansible:
use_ramdisk_callback: true
sources:
openstack/ironic:
git_url: https://git.openstack.org/openstack/ironic.git
git_ref: stable/newton
openstack/ironic-staging-drivers:
git_url: https://git.openstack.org/openstack/ironic-staging-drivers
git_ref: master

View File

@ -0,0 +1,88 @@
[DEFAULT]
debug = {{ ironic.logging_debug }}
use_syslog = false
use_stderr = true
my_ip = {{ network_topology["private"]["address"] }}
transport_url = rabbit://{{ rabbitmq.user }}:{{ rabbitmq.password }}@{{ address('rabbitmq', rabbitmq.port) }}
enabled_drivers = {{ ironic.enabled_drivers }}
enabled_network_interfaces = noop,flat
default_network_interface = flat
[api]
public_endpoint = http://{{ address('ironic', ironic.api_port, external=True, with_scheme=False) }}
host_ip = {{ network_topology["private"]["address"] }}
port = {{ ironic.api_port.cont }}
[database]
connection = mysql+pymysql://{{ ironic.db.username }}:{{ ironic.db.password }}@{{ address('mariadb', mariadb.port) }}/{{ ironic.db.name }}
max_retries = -1
[keystone_authtoken]
auth_uri = {{ address('keystone', keystone.public_port, with_scheme=True) }}
auth_url = {{ address('keystone', keystone.admin_port, with_scheme=True) }}
auth_type = password
project_domain_id = default
user_domain_id = default
project_name = service
username = {{ ironic.username }}
password = {{ ironic.password }}
memcached_servers = {{ address('memcached', memcached.port) }}
[service_catalog]
auth_type = password
auth_url = {{ address('keystone', keystone.public_port, with_scheme=True) }}
project_domain_id = default
user_domain_id = default
project_name = service
username = {{ ironic.username }}
password = {{ ironic.password }}
[conductor]
api_url = http://{{ address('ironic', ironic.api_port, external=True, with_scheme=False) }}
automated_clean = {{ ironic.automated_clean }}
[neutron]
auth_type = password
auth_url = {{ address('keystone', keystone.public_port, with_scheme=True) }}
project_domain_id = default
user_domain_id = default
project_name = service
username = {{ ironic.username }}
password = {{ ironic.password }}
url={{ address('neutron-server', neutron.server_port, with_scheme=True) }}
[glance]
auth_type = password
auth_url = {{ address('keystone', keystone.public_port, with_scheme=True) }}
project_domain_id = default
user_domain_id = default
project_name = service
username = {{ ironic.username }}
password = {{ ironic.password }}
glance_api_servers = {{ address('glance-api', glance.api_port, with_scheme=True) }}
swift_endpoint_url = http://{{ address('radosgw', radosgw.port, external=True, with_scheme=False) }}
swift_temp_url_key = {{ ironic.swift.temp_url_key }}
temp_url_endpoint_type = radosgw
[pxe]
pxe_append_params = nofb nomodeset vga=normal
tftp_root = /var/lib/ironic/tftpboot
tftp_master_path = /var/lib/ironic/tftpboot/master_images
ipxe_enabled = true
ipxe_use_swift = {{ ironic.ipxe.use_swift }}
pxe_bootfile_name=undionly.kpxe
pxe_config_template=$pybasedir/drivers/modules/ipxe_config.template
[deploy]
http_root=/var/lib/ironic/httpboot
http_url=http://{{ network_topology["private"]["address"] }}:{{ ironic.ipxe.external_port }}
[ansible]
use_ramdisk_callback = {{ ironic.ansible.use_ramdisk_callback }}

View File

@ -0,0 +1,4 @@
server {
listen {{ network_topology["private"]["address"] }}:{{ ironic.ipxe.external_port }};
root /var/lib/ironic/httpboot;
}

View File

@ -0,0 +1,14 @@
#!/bin/bash
set -e
mkdir -p /var/lib/ironic/tftpboot /var/lib/ironic/httpboot
cp \
/usr/lib/PXELINUX/pxelinux.0 \
/usr/lib/syslinux/modules/bios/chain.c32 \
/usr/lib/syslinux/modules/bios/ldlinux.c32 \
/usr/lib/ipxe/undionly.kpxe \
/var/lib/ironic/tftpboot
chown -R ironic:ironic /var/lib/ironic

3
service/files/ssh_key.j2 Normal file
View File

@ -0,0 +1,3 @@
{% if ironic.ssh_key -%}
{{ ironic.ssh_key}}
{% endif %}

73
service/ironic-api.yaml Normal file
View File

@ -0,0 +1,73 @@
dsl_version: 0.1.0
service:
name: ironic-api
ports:
- {{ ironic.api_port }}
containers:
- name: ironic-api
image: ironic-api
privileged: true
probes:
readiness: "true"
liveness:
command: "true"
type: "exec"
pre:
- name: ironic-db-create
type: single
command: mysql -v -u root -p{{ db.root_password }} -h {{ address('mariadb') }} -P {{ mariadb.port.cont }} -e
'create database `{{ ironic.db.name }}`; grant all privileges on `{{ ironic.db.name }}`.* to
"{{ ironic.db.username }}"@"%" identified by "{{ ironic.db.password }}"'
dependencies:
- mariadb
- name: ironic-db-sync
type: single
command: ironic-dbsync
dependencies:
- ironic-db-create
files:
- ironic.conf
- name: ironic-user-create
type: single
command: openstack user create --project service --password {{ ironic.password }} {{ ironic.username }}
dependencies:
- keystone-create-project
- name: ironic-role-add
dependencies:
- ironic-user-create
type: single
command: openstack role add --project service --user {{ ironic.username }} admin
- name: ironic-service-create
dependencies:
- keystone
type: single
command: openstack service create --name ironic --description "OpenStack Baremetal" baremetal
- name: ironic-public-endpoint-create
dependencies:
- ironic-service-create
type: single
command: openstack endpoint create --region RegionOne baremetal public
{{ address('ironic-api', ironic.api_port, external=True, with_scheme=True) }}
- name: ironic-internal-endpoint-create
dependencies:
- ironic-service-create
type: single
command: openstack endpoint create --region RegionOne baremetal internal
{{ address('ironic-api', ironic.api_port, with_scheme=True) }}
- name: ironic-admin-endpoint-create
dependencies:
- ironic-service-create
type: single
command: openstack endpoint create --region RegionOne baremetal admin
{{ address('ironic-api', ironic.api_port, with_scheme=True) }}
daemon:
command: ironic-api --config-file /etc/ironic/ironic.conf
files:
- ironic.conf
dependencies:
- rabbitmq
files:
ironic.conf:
path: /etc/ironic/ironic.conf
content: ironic.conf.j2
perm: "0600"

View File

@ -0,0 +1,87 @@
dsl_version: 0.1.0
service:
name: ironic-conductor
hostNetwork: true
kind: DaemonSet
containers:
- name: ironic-conductor
image: ironic-conductor
probes:
readiness: "true"
liveness:
command: "true"
type: "exec"
volumes:
- name: ironic
type: host
path: /var/lib/ironic
pre:
- name: ironic-post-swift-tempurl-key
dependencies:
- radosgw
type: single
command: swift --insecure
--os-auth-url {{ address('keystone', keystone.public_port, with_scheme=True) }}/v3
--os-project-name service --os-project-domain-name default --os-user-domain-name default
--os-username {{ glance.user }} --os-password {{ glance.password }} --os-endpoint-type internalURL
post -m "Temp-URL-Key:{{ ironic.swift.temp_url_key }}"
daemon:
command: ironic-conductor --config-file /etc/ironic/ironic.conf
files:
- ironic.conf
- ssh_key
dependencies:
- ironic-db-sync
- ironic-post-swift-tempurl-key
- name: ironic-pxe
image: ironic-pxe
probes:
readiness: "true"
liveness:
command: "true"
type: "exec"
volumes:
- name: ironic
type: host
path: /var/lib/ironic
pre:
- name: pxe-bootstrap
command: /opt/ccp/bin/pxe-bootstrap.sh
daemon:
command: in.tftpd --verbose --foreground --user root --map-file /map-file
--address {% raw %}{{ network_topology["private"]["address"] }}{% endraw %}:69
/var/lib/ironic/tftpboot
files:
- pxe-bootstrap.sh
- name: ironic-ipxe
image: ironic-ipxe
probes:
readiness: "true"
liveness:
command: "true"
type: "exec"
volumes:
- name: ironic
type: host
path: /var/lib/ironic
daemon:
command: nginx -g 'daemon off; error_log stderr;'
files:
- nginx-ipxe.conf
files:
ironic.conf:
path: /etc/ironic/ironic.conf
content: ironic.conf.j2
perm: "0600"
pxe-bootstrap.sh:
path: /opt/ccp/bin/pxe-bootstrap.sh
content: pxe-bootstrap.sh
perm: "0755"
nginx-ipxe.conf:
path: /etc/nginx/sites-enabled/nginx-ipxe.conf
content: nginx-ipxe.conf.j2
perm: "0644"
ssh_key:
path: /home/ironic/.ssh/id_rsa
content: ssh_key.j2
perm: "0400"

2
test-requirements.txt Normal file
View File

@ -0,0 +1,2 @@
yamllint>=1.3.2
bashate>=0.2

5
tools/yamllint.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
workdir=$(dirname $0)
yamllint -c $workdir/yamllint.yaml $(find . -not -path '*/\.*' -type f -name '*.yaml')

21
tools/yamllint.yaml Normal file
View File

@ -0,0 +1,21 @@
extends: default
rules:
braces:
max-spaces-inside: 1
comments:
level: error
comments-indentation:
level: warning
document-end:
present: no
document-start:
level: error
present: no
empty-lines:
max: 1
max-start: 0
max-end: 0
line-length:
level: warning
max: 120

15
tox.ini Normal file
View File

@ -0,0 +1,15 @@
[tox]
minversion = 1.6
envlist = linters,bashate
skipsdist = True
[testenv]
deps = -r{toxinidir}/test-requirements.txt
[testenv:linters]
commands =
{toxinidir}/tools/yamllint.sh
[testenv:bashate]
whitelist_externals = bash
commands = bash -c "find {toxinidir} -type f -name '*.sh' -not -path '*/.tox/*' -print0 | xargs -0 bashate -v"