di.png

Resumen

OpenStack es un software para la creación de clouds. El proyecto OpenStack ofrece gran cantidad de componentes para implementar los diferentes servicios que se quieran desplegar en nuestro cloud (máquinas virtuales, infraestructura de red, almacenamiento de bloques, almacenamiento de archivos compartidos, almacenamiento de objetos, orquestación, monitorización, por citar algunos). OpenStack tiene una arquitectura totalmente modular en la que partiendo de los componentes básicos (Keystone para autenticación, Glance para imágenes, Neutron para redes y Nova para instancias) podemos ir añadiendo los componentes adecuados para poder desplegar los servicios que queremos ofrecer.

En este tutorial se describen los pasos de instalación de los componentes que actualmente están disponibles en OpenStack-DI.

El acceso a OpenStack-DI y a otros recursos más de Cloud-DI se puede hacer directamente desde https://openstack.di.ual.es/horizon o desde la web de servicios de Cloud-DI https://cloud.di.ual.es. Allí además hay disponible una lista de respuestas a preguntas frecuentes y los Términos de servicio de Cloud-DI.

En https://moodle.di.ual.es se encuentran disponibles una serie de videos ilustrativos sobre los sevicios ofrecidos por Cloud-DI y sobre las operaciones básicas para el uso de OpenStack-DI.

Para realizar operaciones repetitivas o avanzadas es conveniente utilizar el CLI. Aquí está disponible la Lista de comandos CLI.

1. Componentes de OpenStack

OpenStack es un proyecto formado por distintos componentes. Cada uno de ellos añade una función a nuestro cloud (networking, almacenamiento, máquinas virtuales, orquestación, …​). Podemos clasificar estos componentes en básicos y opcionales.

  • Componentes básicos

    • Keystone: Servicio de Identidad (*)

    • Neutron: Servicio de redes (*)

    • Glance: Servicio de imágenes (*)

    • Nova: Servicio de cómputo (máquinas virtuales) (*)

  • Componentes opcionales

    • Horizon: Interfaz web (*)

    • Cinder: Almacenamiento de bloques (*)

    • Manila: Servicio de sistemas de archivos compartidos (*)

    • Swift: Servicio de almacenamiento de objetos (*)

    • Sahara: Servicio de procesamiento de datos (*)

    • Ceilometer: Servicio de recolección de datos de telemetría

    • Aodh: Servicio de alerta de telemetría

    • Heat: Servicio de orquestación (*)

    • Barbican: Servicio de gestión de claves (*)

    • Ironic: Aprovisionamiento en máquinas físicas

    • Cloudkitty: Servicio de tarificación

Los componentes marcardos con asterisco (*) están disponibles actualmente en OpenStack-DI.

La figura siguiente ilustra los componentes instalados en OpenStack-DI y su interacción básica. Los componentes en rojo son los componentes básicos.

ComponentesOpenStack.png
Figure 1. Componentes de OpenStack-DI
  • Keystone proporciona servicios de identificación a todos los componentes OpenStack

  • Horizon proporciona un portal web de acceso al resto de componentes salvo a Keystone.

  • Glance proporciona las imágenes al crear las máquinas virtuales.

  • Neutron proporciona los servicios de networking a las máquinas virtuales

  • Cinder propociona almacenamiento de bloques a las máquinas virtuales. Cinder también puede guardar snapshots de volumen.

  • Manila propociona servicios de almacenamiento compartido de archivos a las máquinas virtuales

  • Swift propociona almacenamiento de objetos a las máquinas virtuales y a Sahara. Opcionalmente se puede configurar Nova para almacenar las imágenes en Swift.

  • Ceilometer recoge medidas de uso de los componentes de networking, imágenes, cómputo, almacenamiento y procesamiento de datos.

  • Heat permite la creación de stacks para la creación de infraestructura mediante código. Opcionalmente se puede combinar con Ceilometer par ajustar dinánicamente la infraestructura en función del uso de recursos (RAM, cores, almacenamiento) recopilado por Ceilometer.

Los componentes de OpenStack exponen una API que es usada por los distintos servicios. Cada componente también suele utilizar una base de datos donde registra sus elementos, estado, operaciones, y demás. La comunicación con la base de datos se realiza con el protocolo AMQP.

2. Preparación del entorno

Para la instalación de los componentes de este tutorial partimos del siguiente escenario en el que contaremos con servidores dedicados para Control, Red y Cómputo. Los servicios de almacenamiento tienen los requisitos siguientes:

  • Cinder: Almacenamiento en un NAS Synology y servicios ejecutándose en el nodo de Control.

  • Manila: Servidor independiente.

  • Swift: Dos servidores para proporcionar tolerancia a fallos.

La figura siguiente ilustra la arquitectura de referencia que usaremos en este tutorial. Tal y como aparece en la Guía de networking en la instalación de OpenStack dispondremos de una red de mantenimiento, una red de túnel y la red externa.

configuracionDeseable.png
Figure 2. Configuración y conexión de servidores

Como se observa en la figura, todos los servidores están conectados a las redes de mantenimiento y túnel.

Además, los servidores siguientes están contectados al exterior a través de una red externa, que proporciona conexión a Internet a las máquinas virtuales, y en el caso de OpenStack-DI al almacenamiento de archivos compartidos.

  • Control: Proporciona acceso a la consola de Horizon en la red de la UAL.

  • Red: Ofrece conectividad a la red de la UAL a las máquinas virtuales.

  • Almacenamiento compartido: Permite ofrecer sistemas de archivos de compartidos en la red de la UAL.

La red de mantenimiento proporciona comunicación interna entre los componentes de OpenStack. La red de túnel (también conocida como guest) proporciona comunicación a las máquinas virtuales con los recursos del cloud.

Los requisitos hardware mínimos de cada servidor son los que aparecen el la arquitectura de ejemplo de la guía de instalación de OpenStack.

Si dispones de recursos en una plataforma OpenStack que disponga del componente Heat instalado, puedes usar esta plantilla Heat para crear la infraestructura. El script denomina lowcost-net a la red externa. En la documentación de OpenStack suele denominarse ext-net.

2.1. Configuración de las interfaces de red

Es recomendable, aunque no necesario, una nomenclatura uniforme de las interfaces de red de los servidores que ofrecen la infraestructura a OpenStack. Si hay diferencias, recomendamos seguir la denominación clásica eth0, eth1, …​ Sigue como root estos pasos cambiar los nombres de la interfaces de red a eth0, eth1, …​

  1. Editar /etc/default/grub y cambiar la línea GRUB_CMDLINE_LINUX="" por GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0".

  2. Actualizar GRUB con update-grub.

  3. Actualizar el archivo /etc/network/interfaces con las interfaces de red ya a eth0, eth1, …​

  4. Reiniciar el sistema con reboot

3. Preparación de las máquinas

  1. En cada máquina crear un archivo /etc/hosts con las direcciones IP de la red de mantenimiento y los nombres que vayamos a dar a las máquinas:

    10.0.0.51 testcontroller
    
    10.0.0.52 testnetwork
    
    10.0.0.53 testcompute01
    10.0.0.54 testcompute02
    10.0.0.55 testcompute03
    10.0.0.56 testcompute04
    
    10.0.0.61 testobject01
    10.0.0.62 testobject02
    
    10.0.0.63 testshared
  2. Instalar chrony en todas las máquinas

    # apt-get install chrony
  3. Modificar en la máquina de control el archivo /etc/chrony/chrony.conf

    Archivo /etc/chrony/chrony.conf en el nodo de control
    pool 2.debian.pool.ntp.org offline iburst
    
    server 1.es.pool.ntp.org iburst (1)
    allow 10.0.0.0/24 (2)
    
    keyfile /etc/chrony/chrony.keys
    
    commandkey 1
    
    driftfile /var/lib/chrony/chrony.drift
    
    log tracking measurements statistics
    logdir /var/log/chrony
    
    maxupdateskew 100.0
    
    dumponexit
    
    dumpdir /var/lib/chrony
    
    logchange 0.5
    
    hwclockfile /etc/adjtime
    
    rtcsync
    1 Servidor NTP
    2 Red de mantenimiento
  4. Modificar en el resto de máquinas el archivo /etc/chrony/chrony.conf

    Archivo /etc/chrony/chrony.conf en el resto de nodos

    server {{ nodes.controller.name }} iburst (1)
    
    keyfile /etc/chrony/chrony.keys
    
    commandkey 1
    
    driftfile /var/lib/chrony/chrony.drift
    
    log tracking measurements statistics
    logdir /var/log/chrony
    
    maxupdateskew 100.0
    
    dumponexit
    
    dumpdir /var/lib/chrony
    
    logchange 0.5
    
    hwclockfile /etc/adjtime
    
    rtcsync
    1 Nombre del servidor de control
  5. Reiniciar chrony en todos los nodos

    # service chrony restart
  6. Revisar funcionamiento de chrony en todos los nodos

    # chronyc sources
  7. Añadir el repositorio de OpenStack Ocata en todos los nodos

    # apt-get install software-properties-common
    # add-apt-repository cloud-archive:ocata
    # apt update && apt dist-upgrade
  8. Instalar el cliente Python para OpenStack en todos los nodos

    # apt install python-openstackclient
  9. Instalar la base de datos en el nodo de control

    # apt-get install mariadb-server python-pymysql libmysqlclient-dev
  10. Modificar el archivo /etc/mysql/mariadb.conf.d/99-openstack.cnf en el nodo de control

    Archivo /etc/mysql/mariadb.conf.d/99-openstack.cnf
    [mysqld]
    bind-address = {{ nodes.controller.management_ip }} (1)
    
    default-storage-engine = innodb
    innodb_file_per_table = on
    max_connections = 4096
    collation-server = utf8_general_ci
    character-set-server = utf8
    1 Dirección IP de mantenimiento del nodo de control
  11. Modificar el archivo /root/my.cnf en el nodo de control

    Archivo /root/my.cnf
    [client]
    user=root
    password={{ mysql_root_password }} (1)
    1 Contraseña del usuario root de MySQL
    # service mysql restart
    # mysql_secure_installation
  12. Instalar la cola de mensajes en el nodo de control

    # apt install rabbitmq-server
    # rabbitmqctl add_user openstack {{ RABBIT_PASS }} (1)
    # rabbitmqctl set_permissions openstack ".*" ".*" ".*"
    1 Contraseña de RabbitMQ
  13. Instalar Memcached en el nodo de control

    # apt install memcached python-memcache
  14. Modificar el archivo /etc/memcached.conf

    Archivo /etc/memcached.conf
    -d
    
    logfile /var/log/memcached.log
    
    -m 64
    
    -p 11211
    
    -u memcache
    
    -l {{ nodes.controller.management_ip }} (1)
    1 Dirección IP de mantenimiento del nodo de control
  15. Reiniciar Memcached

    # service memcached restart

4. Instalación de Keystone

La instalación de Keystone se realiza en el nodo de control

  1. Creación y configuración de la base de datos keystone

    MariaDB [(none)]> CREATE DATABASE keystone;
    Grant proper access to the keystone database:
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \
    IDENTIFIED BY {{ 'KEYSTONE_DBPASS' }}; (1)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \
    IDENTIFIED BY {{ 'KEYSTONE_DBPASS' }}; (2)
    1 Contraseña del usuario Keystone
    2 Contraseña del usuario Keystone
  2. Instalar los paquetes de Keystone

    # apt install keystone
  3. Configurar el archivo /etc/keystone/keystone.conf

    El archivo /etc/keystone/keystone.conf
    [DEFAULT]
    
    [assignment]
    
    [auth]
    
    [cache]
    
    [catalog]
    
    [cors]
    
    [cors.subdomain]
    
    [credential]
    
    [database]
    
    connection = mysql+pymysql://keystone:{{ keystone_dbpass }}@{{ nodes.controller.name }}/keystone (1)
    
    [domain_config]
    
    [endpoint_filter]
    
    [endpoint_policy]
    
    [eventlet_server]
    
    [extra_headers]
    
    [federation]
    
    [fernet_tokens]
    
    [healthcheck]
    
    [identity]
    
    [identity_mapping]
    
    [kvs]
    
    [ldap]
    
    [matchmaker_redis]
    
    [memcache]
    
    [oauth1]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [paste_deploy]
    
    [policy]
    
    [profiler]
    
    [resource]
    
    [revoke]
    
    [role]
    
    [saml]
    
    [security_compliance]
    
    [shadow_users]
    
    [signing]
    
    [token]
    
    provider = fernet
    
    [tokenless_auth]
    
    [trust]
    1 Contraseña del usuario Keystone y nombre del nodo de control
  4. Reiniciar MySQL

    # service mysql restart
  5. Inicializar la base de datos Keystone:

    # su -s /bin/sh -c "keystone-manage db_sync" keystone
  6. Inicializar los repositorios de claves Fernet

    # keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
    # keystone-manage credential_setup --keystone-user keystone --keystone-group keystone
  7. Iniciar los servicios de Keystone

    keystone-manage bootstrap --bootstrap-password {{ admin_pass}} --bootstrap-admin-url http://{{ nodes_by_name.controller.management_ip }}:35357/v3/ --bootstrap-internal-url http://{{ nodes_by_name.controller.tunnel_ip }}:5000/v3/ --bootstrap-public-url http://{{ nodes_by_name.controller.provider_ip}}:5000/v3/ --bootstrap-region-id {{ region }} (1)
    1 Completar con la contraseña de admin, las direcciones IP del nodo de control y el nombre de la región (p.e. RegionOne)
  8. Configurar el archivo /etc/apache2/apache2.conf

    El archivo /etc/apache2/apache2.conf
    Mutex file:${APACHE_LOCK_DIR} default
    
    PidFile ${APACHE_PID_FILE}
    
    Timeout 300
    
    KeepAlive On
    
    MaxKeepAliveRequests 100
    
    KeepAliveTimeout 5
    
    User ${APACHE_RUN_USER}
    Group ${APACHE_RUN_GROUP}
    
    HostnameLookups Off
    
    ErrorLog ${APACHE_LOG_DIR}/error.log
    
    LogLevel warn
    
    IncludeOptional mods-enabled/*.load
    IncludeOptional mods-enabled/*.conf
    
    Include ports.conf
    
    <Directory />
    	Options FollowSymLinks
    	AllowOverride None
    	Require all denied
    </Directory>
    
    <Directory /usr/share>
    	AllowOverride None
    	Require all granted
    </Directory>
    
    <Directory /var/www/>
    	Options Indexes FollowSymLinks
    	AllowOverride None
    	Require all granted
    </Directory>
    
    AccessFileName .htaccess
    
    <FilesMatch "^\.ht">
    	Require all denied
    </FilesMatch>
    
    LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
    LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %O" common
    LogFormat "%{Referer}i -> %U" referer
    LogFormat "%{User-agent}i" agent
    
    IncludeOptional conf-enabled/*.conf
    
    IncludeOptional sites-enabled/*.conf
    
    ServerName {{ nodes.controller.name }} (1)
    1 Configurar ServerName con el nombre del nodo de control
  9. Reiniciar Apache

    # service apache2 restart
  10. Eliminar la base de datos SQLite predetermianda

    # rm -rf /var/lib/keystone/keystone.db
  11. Configurar el archivo de credenciales del usuario admin. Crear un archivo denominado openrc-admin.

    export OS_USERNAME=admin
    export OS_PASSWORD={{ admin_pass }} (1)
    export OS_PROJECT_NAME=admin
    export OS_USER_DOMAIN_NAME=Default
    export OS_PROJECT_DOMAIN_NAME=Default
    export OS_AUTH_URL=http://{{ nodes.controller.name }}:35357/v3 (2)
    export OS_IDENTITY_API_VERSION=3
    export OS_IMAGE_API_VERSION=2
    export OS_AUTH_TYPE=password
    1 Contraseña de admin
    2 Nombre del nodo de control
  12. Configurar el archivo de credenciales del usuario demo. Crear un archivo denominado openrc-demo.

    export OS_USERNAME=demo
    export OS_PASSWORD={{ demo_pass }} (1)
    export OS_PROJECT_NAME=demo
    export OS_USER_DOMAIN_NAME=Default
    export OS_PROJECT_DOMAIN_NAME=Default
    export OS_AUTH_URL=http://{{ nodes.controller.name }}:5000/v3 (2)
    export OS_IDENTITY_API_VERSION=3
    export OS_IMAGE_API_VERSION=2
    export OS_AUTH_TYPE=password
    1 Contraseña de demo
    2 Nombre del nodo de control
  13. Realizar la configuración de Keystone (dominio default, proyectos service y demo, usuario demo, rol user y añadir el usuario demo al proyecto demo con el rol user)

    # source openrc-admin (1)
    
    # openstack domain create --description "Default Domain" default
    # openstack project create --domain default --description "Service Project" service
    # openstack project create --domain default --description "Demo Project" demo
    # openstack user create --domain default demo --password {{ demo_pass }} (2)
    # openstack role create user
    # openstack role add --project demo --user demo user
    1 Cargar las credenciales de admin
    2 Contraseña del usuario demo
  14. Configurar el archivo /etc/keystone/keystone-paste.ini

El archivo /etc/keystone/keystone-paste.ini
[filter:debug]
use = egg:oslo.middleware#debug

[filter:request_id]
use = egg:oslo.middleware#request_id

[filter:build_auth_context]
use = egg:keystone#build_auth_context

[filter:token_auth]
use = egg:keystone#token_auth

[filter:admin_token_auth]
use = egg:keystone#admin_token_auth

[filter:json_body]
use = egg:keystone#json_body

[filter:cors]
use = egg:oslo.middleware#cors
oslo_config_project = keystone

[filter:http_proxy_to_wsgi]
use = egg:oslo.middleware#http_proxy_to_wsgi

[filter:healthcheck]
use = egg:oslo.middleware#healthcheck

[filter:ec2_extension]
use = egg:keystone#ec2_extension

[filter:ec2_extension_v3]
use = egg:keystone#ec2_extension_v3

[filter:s3_extension]
use = egg:keystone#s3_extension

[filter:url_normalize]
use = egg:keystone#url_normalize

[filter:sizelimit]
use = egg:oslo.middleware#sizelimit

[filter:osprofiler]
use = egg:osprofiler#osprofiler

[app:public_service]
use = egg:keystone#public_service

[app:service_v3]
use = egg:keystone#service_v3

[app:admin_service]
use = egg:keystone#admin_service

[pipeline:public_api]
pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id build_auth_context token_auth json_body ec2_extension public_service

[pipeline:admin_api]
pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id build_auth_context token_auth json_body ec2_extension s3_extension admin_service

[pipeline:api_v3]
pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id build_auth_context token_auth json_body ec2_extension_v3 s3_extension service_v3

[app:public_version_service]
use = egg:keystone#public_version_service

[app:admin_version_service]
use = egg:keystone#admin_version_service

[pipeline:public_version_api]
pipeline = healthcheck cors sizelimit osprofiler url_normalize public_version_service

[pipeline:admin_version_api]
pipeline = healthcheck cors sizelimit osprofiler url_normalize admin_version_service

[composite:main]
use = egg:Paste#urlmap
/v2.0 = public_api
/v3 = api_v3
/ = public_version_api

[composite:admin]
use = egg:Paste#urlmap
/v2.0 = admin_api
/v3 = api_v3
/ = admin_version_api

5. Instalación de Glance

La instalación de Glance se realiza en el nodo de control.

  1. Creación y configuración de la base de datos glance

    MariaDB [(none)]> CREATE DATABASE glance;
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \
      IDENTIFIED BY 'GLANCE_DBPASS'; (1)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \
      IDENTIFIED BY 'GLANCE_DBPASS'; (2)
    1 Contraseña del usuario Glance
    2 Contraseña del usuario Glance
  2. Realizar la configuración de Glance (usuario glance, añadir el usuario glance al proyecto service con el rol admin y crear el servicio glance)

    # source openrc-admin (1)
    
    # openstack user create --domain default glance --password {{ glance_dbpass }} (1)
    # openstack role add --project service --user glance admin
    # openstack service create --name glance --description "OpenStack Image" image
    1 Cargar las credenciales de admin
    2 Contraseña del usuario glance
  3. Crear los endpoints de la API

    # openstack endpoint create --region {{region}} image public http://{{ nodes_by_name.controller.provider_ip }}:9292 (1)
    # openstack endpoint create --region {{region}} image internal http://{{ nodes_by_name.controller.tunnel_ip }}:9292 (2)
    # openstack endpoint create --region {{region}} image admin http://{{ nodes_by_name.controller.management_ip }}:9292 (3)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  4. Instalar los paquetes de Glance

    # apt install glance
  5. Configurar el archivo /etc/glance/glance-api.conf

    El archivo /etc/glance/glance-api.conf
    [DEFAULT]
    
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (1)
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    sqlite_db = /var/lib/glance/glance.sqlite
    
    backend = sqlalchemy
    
    connection = mysql+pymysql://glance:{{ glance_dbpass }}@{{ nodes.controller.name }}/glance (2)
    
    [glance_store]
    
    stores = file,http
    default_store = file
    filesystem_store_datadir = {{ glance_image_dir }} (3)
    
    [image_format]
    
    disk_formats = ami,ari,aki,vhd,vhdx,vmdk,raw,qcow2,vdi,iso,ploop.root-tar
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (4)
    auth_url = http://{{ nodes.controller.name }}:35357 (5)
    memcached_servers = {{ nodes.controller.name }}:11211 (6)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = glance
    password = {{ glance_dbpass }} (7)
    
    [matchmaker_redis]
    
    [oslo_concurrency]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    driver = messagingv2
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [paste_deploy]
    
    flavor = keystone
    
    [profiler]
    
    [store_type_location_strategy]
    
    [task]
    
    [taskflow_executor]
    1 Contraseña de RabbitMQ y nombre del nodo de control
    2 Contraseña de Glance y nombre del nodo de control
    3 Directorio donde se vayan a almacenar las imágenes (p.e. /var/lib/glance/images)
    4 Nombre del nodo de control
    5 Nombre del nodo de control
    6 Nombre del nodo de control
    7 Contraseña de Glance
  6. Modificar el archivo /etc/glance/glance-registry.conf

El archivo /etc/glance/glance-registry.conf
[DEFAULT]

transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (1)

[database]

sqlite_db = /var/lib/glance/glance.sqlite

backend = sqlalchemy

connection = mysql+pymysql://glance:{{ glance_dbpass }}@{{ nodes.controller.name }}/glance (2)

[keystone_authtoken]

auth_uri = http://{{ nodes.controller.name }}:5000 (3)
auth_url = http://{{ nodes.controller.name }}:35357 (4)
memcached_servers = {{ nodes.controller.name }}:11211 (5)
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = glance
password = {{ glance_dbpass }}

[matchmaker_redis]

[oslo_messaging_amqp]

[oslo_messaging_kafka]

[oslo_messaging_notifications]

driver = messagingv2

[oslo_messaging_rabbit]

[oslo_messaging_zmq]

[oslo_policy]

[paste_deploy]

flavor = keystone

[profiler]
1 Contraseña de RabbitMQ y nombre del nodo de control
2 Contraseña de Glance y nombre del nodo de control
3 Nombre del nodo de control
4 Nombre del nodo de control
5 Nombre del nodo de control
6 Contraseña de Glance
  1. Poblar la base de datos glance.

    # su -s /bin/sh -c "glance-manage db_sync" glance
  2. Reiniciar los servicios de Glance

    # service glance-registry restart
    # service glance-api restart
  3. Verificar funcionaminento

    # wget http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img (1)
    # openstack image create "cirros" \
      --file cirros-0.3.5-x86_64-disk.img \
      --disk-format qcow2 --container-format bare \
      --public (2)
    1 Descargar imagen de prueba de CirrOS
    2 Subir imagen a OpenStack

6. Instalación de Nova

6.1. Instalación de Nova en el nodo de control

Realizar estar operaciones en el nodo de control

  1. Creación y configuración de la base de datos nova

    MariaDB [(none)]> CREATE DATABASE nova_api;
    MariaDB [(none)]> CREATE DATABASE nova;
    MariaDB [(none)]> CREATE DATABASE nova_cell0;
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \
      IDENTIFIED BY 'NOVA_DBPASS'; (1)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \
      IDENTIFIED BY 'NOVA_DBPASS'; (2)
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \
      IDENTIFIED BY 'NOVA_DBPASS'; (3)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \
      IDENTIFIED BY 'NOVA_DBPASS'; (4)
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \
      IDENTIFIED BY 'NOVA_DBPASS'; (5)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \
      IDENTIFIED BY 'NOVA_DBPASS'; (6)
    1 Contraseña del usuario Nova
    2 Contraseña del usuario Nova
    3 Contraseña del usuario Nova
    4 Contraseña del usuario Nova
    5 Contraseña del usuario Nova
    6 Contraseña del usuario Nova
  2. Realizar la configuración de Nova (usuario nova, añadir el usuario nova al proyecto service con el rol admin y crear el servicio nova)

    # source openrc-admin (1)
    
    # openstack user create --domain default nova --password {{ nova_dbpass }} (2)
    # openstack role add --project service --user nova admin
    # openstack service create --name nova --description "OpenStack Compute" compute
    1 Cargar las credenciales de admin
    2 Contraseña del usuario nova
  3. Crear los endpoints de la API

    # openstack endpoint create --region {{ region }} compute public http://{{ nodes_by_name.controller.provider_ip }}:8774/v2.1 (1)
    # openstack endpoint create --region {{ region }} compute internal http://{{ nodes_by_name.controller.tunnel_ip }}:8774/v2.1 (2)
    # openstack endpoint create --region {{ region }} compute admin http://{{ nodes_by_name.controller.management_ip }}:8774/v2.1 (3)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  4. Realizar la configuración del servicio Placement (usuario nova, añadir el usuario nova al proyecto service con el rol admin y crear el servicio nova)

    # source openrc-admin (1)
    
    # openstack user create --domain default placement --password {{ placement_pass }} (2)
    # openstack role add --project service --user placement admin
    # openstack service create --name placement --description "Placement API" placement
    1 Cargar las credenciales de admin
    2 Contraseña del usuario placement
  5. Crear los endpoints de la API

    # openstack endpoint create --region {{ region }} placement public http://{{ nodes_by_name.controller.provider_ip }}:8778 (1)
    # openstack endpoint create --region {{ region }} placement internal http://{{ nodes_by_name.controller.tunnel_ip }}:8778 (2)
    # openstack endpoint create --region {{ region }} placement admin http://{{ nodes_by_name.controller.management_ip }}:8778 (3)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  6. Instalar los paquetes de Nova

    # apt install nova-api nova-conductor nova-consoleauth \
      nova-novncproxy nova-scheduler nova-placement-api
  7. Configurar el archivo /etc/nova/nova.conf

    El archivo /etc/nova/nova.conf
    [DEFAULT]
    my_ip = {{ nodes.controller.management_ip }} (1)
    
    use_neutron = True
    firewall_driver = nova.virt.firewall.NoopFirewallDriver
    
    dhcpbridge_flagfile=/etc/nova/nova.conf
    
    dhcpbridge=/usr/bin/nova-dhcpbridge
    
    linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
    
    force_dhcp_release=true
    
    state_path=/var/lib/nova
    
    enabled_apis=osapi_compute,metadata
    
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (2)
    
    [api]
    
    auth_strategy = keystone
    
    [api_database]
    
    connection = mysql+pymysql://nova:{{ nova_dbpass }}@{{ nodes.controller.name }}/nova_api (3)
    
    [barbican]
    
    [cache]
    
    [cells]
    
    enable=False
    
    [cinder]
    
    os_region_name = {{region}} (4)
    
    [cloudpipe]
    
    [conductor]
    
    [console]
    
    [consoleauth]
    
    [cors]
    
    [cors.subdomain]
    
    [crypto]
    
    [database]
    
    connection = mysql+pymysql://nova:{{ nova_dbpass }}@{{ nodes.controller.name }}/nova (5)
    
    [ephemeral_storage_encryption]
    
    [filter_scheduler]
    
    [glance]
    
    api_servers = http://{{ nodes.controller.name }}:9292 (6)
    
    [guestfs]
    
    [healthcheck]
    
    [hyperv]
    
    [image_file_url]
    
    [ironic]
    
    [key_manager]
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (7)
    auth_url = http://{{ nodes.controller.name }}:35357 (8)
    memcached_servers = {{nodes.controller.name}}:11211 (9)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = nova
    password = {{ nova_dbpass }} (10)
    
    [libvirt]
    
    [matchmaker_redis]
    
    [metrics]
    
    [mks]
    
    [neutron]
    
    url = http://{{ nodes.controller.name }}:9696 (11)
    auth_url = http://{{ nodes.controller.name }}:35357 (12)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    region_name = {{ region }} (13)
    project_name = service
    username = neutron
    password = {{ neutron_dbpass }} (14)
    service_metadata_proxy = true
    metadata_proxy_shared_secret = {{ metadata_secret }} (15)
    
    [notifications]
    
    [osapi_v21]
    
    [oslo_concurrency]
    
    lock_path = /var/lib/nova/tmp
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [pci]
    
    [placement]
    
    os_region_name = {{ region }} (16)
    project_domain_name = Default
    project_name = service
    auth_type = password
    user_domain_name = Default
    auth_url = http://{{ nodes.controller.name }}:35357/v3 (17)
    username = placement
    password = {{ placement_pass }} (18)
    
    [quota]
    
    [rdp]
    
    [remote_debug]
    
    [scheduler]
    
    periodic_task_interval=300
    
    [serial_console]
    
    [service_user]
    
    [spice]
    
    [ssl]
    
    [trusted_computing]
    
    [upgrade_levels]
    
    [vendordata_dynamic_auth]
    
    [vmware]
    
    [vnc]
    
    enabled = true
    vncserver_listen = $my_ip
    vncserver_proxyclient_address = $my_ip
    
    [workarounds]
    
    [wsgi]
    
    api_paste_config=/etc/nova/api-paste.ini
    
    [xenserver]
    
    [xvp]
    1 IP del nodo de control
    2 Contraseña de RabbitMQ y nombre del nodo de control
    3 Contraseña de Nova y nombre del nodo de control
    4 Nombre de la región (p.e. RegionOne)
    5 Contraseña de Nova y nombre del nodo de control
    6 Nombre del nodo de control
    7 Nombre del nodo de control
    8 Nombre del nodo de control
    9 Nombre del nodo de control
    10 Contraseña de Nova
    11 Nombre del nodo de control
    12 Nombre del nodo de control
    13 Nombre de la región (p.e. RegionOne)
    14 Contraseña de Neutron
    15 Secreto para metadatos
    16 Nombre de la región (p.e. RegionOne)
    17 Nombre del nodo de control
    18 Contraseña de Placement
  8. Crear las bases de datos y las celdas cell0 y cell1

    # su -s /bin/sh -c "nova-manage api_db sync" nova
    # su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova
    # su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova 109e1d4b-536a-40d0-83c6-5f121b82b650
    # su -s /bin/sh -c "nova-manage db sync" nova
  9. Reiniciar los servicios

    # service nova-api restart
    # service nova-consoleauth restart
    # service nova-scheduler restart
    # service nova-conductor restart
    # service nova-novncproxy restart
  10. Verificar creación de celdas

    # nova-manage cell_v2 list_cells

6.2. Instalación de Nova en los nodos de cómputo

Realizar estar operaciones en cada uno de los nodos de cómputo

  1. Instalar los paquetes de Nova

    # apt install nova-compute
  2. Configurar el archivo /etc/nova/nova.conf

    El archivo /etc/nova/nova.conf
    [DEFAULT]
    
    my_ip = {{ ansible_eth0.ipv4.address }} (1)
    use_neutron = True
    firewall_driver = nova.virt.firewall.NoopFirewallDriver
    
    network_api_class = nova.network.neutronv2.api.API
    security_group_api = neutron
    
    instance_usage_audit_period=hour
    
    instance_usage_audit=True
    
    dhcpbridge_flagfile=/etc/nova/nova.conf
    
    dhcpbridge=/usr/bin/nova-dhcpbridge
    
    linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
    
    force_dhcp_release=true
    
    state_path=/var/lib/nova
    
    enabled_apis=osapi_compute,metadata
    
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (2)
    
    [api]
    
    auth_strategy = keystone
    
    [api_database]
    
    connection = mysql+pymysql://nova:{{ nova_dbpass }}@{{ nodes.controller.name }}/nova_api (3)
    
    [barbican]
    
    [cache]
    
    [cells]
    
    enable=False
    
    [cinder]
    
    [cloudpipe]
    
    [conductor]
    
    [console]
    
    [consoleauth]
    
    [cors]
    
    [cors.subdomain]
    
    [crypto]
    
    [database]
    
    connection = mysql+pymysql://nova:{{ nova_dbpass }}@{{ nodes.controller.name }}/nova (4)
    
    [ephemeral_storage_encryption]
    
    [filter_scheduler]
    
    [glance]
    
    api_servers = http://{{ nodes.controller.name }}:9292 (5)
    
    [guestfs]
    
    [healthcheck]
    
    [hyperv]
    
    [image_file_url]
    
    [ironic]
    
    [key_manager]
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (6)
    auth_url = http://{{ nodes.controller.name }}:35357 (7)
    memcached_servers = {{ nodes.controller.name }}:11211 (8)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = nova
    password = {{ nova_dbpass }} (9)
    
    [libvirt] (10)
    
    cpu_mode=custom
    
    cpu_model=kvm64
    
    [matchmaker_redis]
    
    [metrics]
    
    [mks]
    
    [neutron]
    
    url = http://{{ nodes.controller.name }}:9696 (11)
    auth_url = http://{{ nodes.controller.name }}:35357 (12)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    region_name = {{ region }} (13)
    project_name = service
    username = neutron
    password = {{ neutron_dbpass }} (14)
    
    [notifications]
    
    notify_on_state_change=vm_and_task_state
    
    [osapi_v21]
    
    [oslo_concurrency]
    
    lock_path = /var/lib/nova/tmp
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    driver = messagingv2
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [pci]
    
    [placement]
    
    os_region_name = {{ region }} (15)
    project_domain_name = Default
    project_name = service
    auth_type = password
    user_domain_name = Default
    auth_url = http://{{ nodes.controller.name }}:35357/v3 (16)
    username = placement
    password = {{ placement_pass }} (17)
    
    [quota]
    
    [rdp]
    
    [remote_debug]
    
    [scheduler]
    
    [serial_console]
    
    [service_user]
    
    [spice]
    
    [ssl]
    
    [trusted_computing]
    
    [upgrade_levels]
    
    [vendordata_dynamic_auth]
    
    [vmware]
    
    [vnc]
    
    enabled = True
    vncserver_listen = 0.0.0.0
    vncserver_proxyclient_address = $my_ip
    novncproxy_base_url = http://{{ nodes_by_name.controller.provider_ip }}:6080/vnc_auto.html (18)
    
    [workarounds]
    
    [wsgi]
    
    api_paste_config=/etc/nova/api-paste.ini
    
    [xenserver]
    
    [xvp]
    1 IP del nodo de cómputo
    2 Contraseña de RabbitMQ y nombre del nodo de control
    3 Contraseña de Nova y nombre del nodo de control
    4 Contraseña de Nova y nombre del nodo de control
    5 Nombre del nodo de control
    6 Nombre del nodo de control
    7 Nombre del nodo de control
    8 Nombre del nodo de control
    9 Contraseña de Nova
    10 Configurar los parámetros cpu_mode y cpu_model de esta forma permite la migración de instancias entre servidores que tengan diferente procesador
    11 Nombre del nodo de control
    12 Nombre del nodo de control
    13 Nombre de la región (p.e. RegionOne)
    14 Contraseña de Neutron
    15 Nombre de la región (p.e. RegionOne)
    16 Nombre del nodo de control
    17 IP externa del nodo de control
  3. Reiniciar servicios de nova

# service nova-compute restart

6.3. Configuración de Nova en el nodo de control

Realizar estar operaciones en el nodo de control

  1. Crear los sabores

    # source openrc-admin (1)
    
    # openstack flavor create --vcpus 1 --ram 512 --disk 1 tiny
    # openstack flavor create --vcpus 1 --ram 2048 --disk 20 small
    # openstack flavor create --vcpus 2 --ram 4096 --disk 40 medium
    # openstack flavor create --vcpus 4 --ram 8192 --disk 80 large
    # openstack flavor create --vcpus 8 --ram 16384 --disk 160 xlarge
    1 Cargar las credenciales de admin
  2. Descubrir los servidores de cómputo

    # su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova

7. Neutron

7.1. Instalación de Neutron en el nodo de control

Realizar estar operaciones en el nodo de control

  1. Creación y configuración de la base de datos neutron

    MariaDB [(none)]> CREATE DATABASE neutron;
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \
      IDENTIFIED BY 'NEUTRON_DBPASS'; (1)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \
      IDENTIFIED BY 'NEUTRON_DBPASS'; (2)
    Exit
    1 Contraseña del usuario Neutron
    2 Contraseña del usuario Neutron
  2. Realizar la configuración de Neutron (usuario neutron, añadir el usuario neutron al proyecto service con el rol admin y crear el servicio neutron)

    # source openrc-admin (1)
    
    # openstack user create --domain default neutron --password {{ neutron_dbpass }} (2)
    # openstack role add --project service --user neutron admin
    # openstack service create --name neutron --description "OpenStack Networking" network
    1 Cargar las credenciales de admin
    2 Contraseña del usuario nova
  3. Crear los endpoints de la API

    # openstack endpoint create --region {{region}} neutron public http://{{ nodes_by_name.controller.provider_ip }}:9696 (1)
    # openstack endpoint create --region {{region}} neutron internal http://{{ nodes_by_name.controller.tunnel_ip }}:9696 (2)
    # openstack endpoint create --region {{region}} neutron admin http://{{ nodes_by_name.controller.management_ip }}:9696 (3)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  4. Instalar los paquetes de Neutron

    # apt install neutron-server neutron-plugin-ml2
  5. Configurar el archivo /etc/neutron/neutron.conf

    Este tutorial deja preparado el archivo /etc/neutron/neutron.conf para la instalación posterior del componente Neutron Load Balancer as a Service (LBaaS). En caso de no instalar tal componente habrá que eliminar la carga de LBaaS en la línea service_plugins del archivo /etc/neutron/neutron.conf. De no eliminar la referencia a LBaaS en /etc/neutron/neutron.conf el componente Neutron no funcionará correctamente.

    El archivo /etc/neutron/neutron.conf
    [DEFAULT]
    
    auth_strategy = keystone
    
    core_plugin = ml2
    
    service_plugins = router,neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2 (1)
    # Sustituir la línea anterior por la línea siguiente si no se va a instalar el componente de Load Balancer as a Service
    # service_plugins = router
    
    allow_overlapping_ips = true
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (2)
    
    notify_nova_on_port_status_changes = true
    
    notify_nova_on_port_data_changes = true
    
    dhcp_agents_per_network = 1
    
    [agent]
    
    root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    connection = mysql+pymysql://neutron:{{ neutron_dbpass }}@{{ nodes.controller.name }}/neutron (3)
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (4)
    auth_url = http://{{ nodes.controller.name }}:35357 (5)
    memcached_servers = {{ nodes.controller.name }}:11211 (6)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = neutron
    password = {{ neutron_dbpass }} (7)
    
    [matchmaker_redis]
    
    [nova]
    
    auth_url = http://{{ nodes.controller.name }}:35357 (8)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    region_name = {{ region }} (9)
    project_name = service
    username = nova
    password = {{ nova_dbpass }} (10)
    
    [oslo_concurrency]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    driver = messagingv2
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [qos]
    
    [quotas]
    
    [ssl]
    1 Sustituir la línea de service_plugins si no se va a instalar el componente Neutron Load Balancer as a Service (LBaaS)
    2 Contraseña de RabbitMQ y nombre del nodo de control
    3 Contraseña de Neutron y nombre del nodo de control
    4 Nombre del nodo de control
    5 Nombre del nodo de control
    6 Nombre del nodo de control
    7 Contraseña de Neutron
    8 Nombre del nodo de control
    9 Nombre de la región (p.e. RegionOne)
    10 Contraseña de Nova
  6. Modificar el archivo /etc/neutron/plugins/ml2/ml2_conf.ini

    El archivo /etc/neutron/plugins/ml2/ml2_conf.ini
    [DEFAULT]
    
    [ml2]
    
    type_drivers = flat,vlan,vxlan
    
    tenant_network_types = vxlan
    
    mechanism_drivers = openvswitch,l2population
    
    extension_drivers = port_security
    
    [ml2_type_flat]
    
    [ml2_type_geneve]
    
    [ml2_type_gre]
    
    [ml2_type_vlan]
    
    [ml2_type_vxlan]
    
    vni_ranges = 1:1000
    
    [securitygroup]
    
    firewall_driver = iptables_hybrid
    
    enable_security_group = true
    
    enable_ipset = true
  7. Poblar la base de datos de Neutron

    # su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
  8. Reiniciar Neutron

# service neutron-server restart

7.2. Instalación de Neutron en el nodo de red

Realizar estos pasos en el nodo de red

En este tutorial seguimos el escenario de provider networks con OpenvSwich.

  1. Configurar el kernel para desactivar el reverse path filtering. Añadir estas líneas el archivo /etc/sysctl.conf

    net.ipv4.ip_forward=1
    net.ipv4.conf.all.rp_filter=0
    net.ipv4.conf.default.rp_filter=0
  2. Cargar la nueva configuración del kernel

    # sysctl -p
  3. Instalar Neutron

    # apt install neutron-openvswitch-agent neutron-l3-agent neutron-dhcp-agent neutron-metadata-agent
  4. Configurar el archivo /etc/neutron/neutron.conf

    Este tutorial deja preparado el archivo /etc/neutron/neutron.conf para la instalación posterior del componente Neutron Load Balancer as a Service (LBaaS). En caso de no instalar tal componente habrá que eliminar la carga de LBaaS en la línea service_plugins del archivo /etc/neutron/neutron.conf. De no eliminar la referencia a LBaaS en /etc/neutron/neutron.conf el componente Neutron no funcionará correctamente.

    El archivo /etc/neutron/neutron.conf
    [DEFAULT]
    
    auth_strategy = keystone
    
    core_plugin = ml2
    
    service_plugins = router,neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2 (1)
    # Sustituir la línea anterior por la línea siguiente si no se va a instalar el componente de Load Balancer as a Service
    # service_plugins = router
    
    allow_overlapping_ips = true
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (2)
    
    notify_nova_on_port_status_changes = true
    
    notify_nova_on_port_data_changes = true
    
    dhcp_agents_per_network = 1
    
    [agent]
    
    root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    connection = mysql+pymysql://neutron:{{ neutron_dbpass }}@{{ nodes.controller.name }}/neutron (3)
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (4)
    auth_url = http://{{ nodes.controller.name }}:35357 (5)
    memcached_servers = {{ nodes.controller.name }}:11211 (6)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = neutron
    password = {{ neutron_dbpass }} (7)
    
    [matchmaker_redis]
    
    [nova]
    
    auth_url = http://{{ nodes.controller.name }}:35357 (8)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    region_name = {{ region }} (9)
    project_name = service
    username = nova
    password = {{ nova_dbpass }} (10)
    
    [oslo_concurrency]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    driver = messagingv2
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [qos]
    
    [quotas]
    
    [ssl]
    1 Sustituir la línea de service_plugins si no se va a instalar el componente Neutron Load Balancer as a Service (LBaaS)
    2 Contraseña de RabbitMQ y nombre del nodo de control
    3 Contraseña de Neutron y nombre del nodo de control
    4 Nombre del nodo de control
    5 Nombre del nodo de control
    6 Nombre del nodo de control
    7 Contraseña de Neutron
    8 Nombre del nodo de control
    9 Nombre de la región (p.e. RegionOne)
    10 Contraseña de Nova
  5. Modificar el archivo /etc/neutron/l3_agent.ini

    El archivo /etc/neutron/l3_agent.ini
    [DEFAULT]
    
    interface_driver = openvswitch
    
    agent_mode = legacy
    
    handle_internal_only_routers = true
    
    enable_metadata_proxy = true
    
    external_network_bridge =
    
    [agent]
    
    [ovs]
  6. Modificar el archivo /etc/neutron/dhcp_agent.ini

    El archivo /etc/neutron/dhcp_agent.ini
    [DEFAULT]
    
    ovs_integration_bridge = br-int
    
    interface_driver = openvswitch
    
    dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
    
    enable_isolated_metadata = true
    
    dnsmasq_config_file = /etc/neutron/dnsmasq-neutron.conf
    
    [agent]
    
    [ovs]
  7. Modificar el archivo /etc/neutron/dnsmasq-neutron.conf

    El archivo /etc/neutron/dnsmasq-neutron.conf
     -s
    dhcp-option-force=26,1450
  8. Modificar el archivo /etc/neutron/metadata_agent.ini

    El archivo /etc/neutron/metadata_agent.ini
    [DEFAULT]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (1)
    auth_url = http://{{ nodes.controller.name }}:35357 (2)
    auth_region = {{ region }} (3)
    auth_plugin = password
    project_domain_id = default
    user_domain_id = default
    project_name = service
    username = neutron
    password = {{ neutron_dbpass }} (4)
    
    nova_metadata_ip = {{ nodes.controller.management_ip }} (5)
    
    nova_metadata_port = 8775
    
    metadata_proxy_shared_secret = {{ metadata_secret }} (6)
    
    nova_metadata_protocol = http
    
    [agent]
    
    [cache]
    1 Nombre del nodo de control
    2 Nombre del nodo de control
    3 Nombre de la región (p.e. RegionOne)
    4 Contraseña de Neutron
    5 IP de mantenimiento del nodo de control
    6 Secreto para metadatos
  9. Modificar el archivo /etc/neutron/plugins/ml2/openvswitch_agent.ini

    El archivo /etc/neutron/plugins/ml2/openvswitch_agent.ini
    [ovs]
    integration_bridge = br-int
    
    int_peer_patch_port = patch-tun
    
    local_ip = {{ ansible_eth1.ipv4.address }} (1)
    
    bridge_mappings = provider:br-ex
    
    [agent]
    
    polling_interval = 15
    
    tunnel_types = vxlan
    
    l2_population = True
    
    arp_responder = False
    
    enable_distributed_routing = False
    
    [securitygroup]
    firewall_driver = iptables_hybrid
    
    enable_security_group = True
    1 IP de la red de túnel del nodo de red
  10. Reiniciar el servicio openvswitch-switch

    # service openvswitch-switch restart
  11. Añadir el bridge externo

    # ovs-vsctl add-br br-ex
  12. Añadir puerto al bridge externo

    # ovs-vsctl add-port br-ex {{ provider_interface }} (1)
    1 Nombre de la interfaz de red externa en el nodo de red
  13. Añadir el bridge interno

    # ovs-vsctl add-br br-int
  14. Crear el siguiente script en /root/br-ex_setup.sh para configurar la interfaz externa en el nodo de red. Ejecutar el script.

    El archivo /root/br-ex_setup.sh
    /sbin/ip route |grep default |grep br-ex
    
    if [ $? -ne 0 ]; then
        /sbin/ip route del default
        /sbin/ip addr del {{ nodes_by_name.network.provider_ip }}/24 dev {{ provider_interface }}
        /sbin/ip link set br-ex up
        /sbin/ip link set {{ provider_interface }} promisc on
        /sbin/ip addr add {{ nodes_by_name.network.provider_ip }}/24 dev br-ex
        /sbin/ip route add default via {{ provider_gateway }}
    fi
  15. Configurar el archivo /etc/network/interfaces para añadir el bridge externo

    El archivo /etc/network/interfaces
    # This file describes the network interfaces available on your system
    # and how to activate them. For more information, see interfaces(5).
    
    # The loopback network interface
    auto lo
    iface lo inet loopback
    
    # The management network interface
    auto {{management_interface}} (1)
    iface {{management_interface}} inet static (2)
      address {{ nodes_by_name.network.management_ip }} (3)
      netmask {{ management_mask }} (4)
      network {{management_network}} (5)
      mtu {{ MTU }} (6)
    
    # The tunnel network interface
    auto {{tunnel_interface}} (7)
    iface {{tunnel_interface}} inet static (8)
      address {{ nodes_by_name.network.tunnel_ip }} (9)
      netmask {{ tunnel_mask }} (10)
      network {{tunnel_network}} (11)
      mtu {{ MTU }} (12)
    
    auto br-ex
    allow-ovs br-ex
    iface br-ex inet static
      address {{ nodes_by_name.network.provider_ip }} (13)
      netmask {{ provider_mask }} (14)
      gateway {{ provider_gateway }} (15)
      dns-nameservers {{ dns }} (16)
      ovs_type OVSBridge
      ovs_ports {{ provider_interface }} (17)
    
    allow-br-ex {{ provider_interface }} (18)
    iface {{ provider_interface }} inet manual (19)
       ovs_bridge br-ex
      ovs_type OVSPort
      up ip link set $IFACE promisc on
      down ip link set $IFACE promisc off
    1 Nombre de la interfaz de mantenimiento del nodo de red
    2 Nombre de la interfaz de mantenimiento del nodo de red
    3 Dirección IP de mantenimiento del nodo de red
    4 Máscara de red la red de mantenimiento
    5 Red de mantenimiento
    6 MTU
    7 Nombre de la interfaz de túnel del nodo de red
    8 Nombre de la interfaz de túnel del nodo de red
    9 Dirección IP de túnel del nodo de red
    10 Máscara de red la red de túnel
    11 Red de mantenimiento
    12 MTU
    13 Dirección IP externa del nodo de red
    14 Máscara de red la red externa
    15 Gateway de la red external
    16 IP del DNS
    17 Nombre de la interfaz de red externa
    18 Nombre de la interfaz de red externa
    19 Nombre de la interfaz de red externa
  16. Reiniciar los servicios de Neutron

    # service neutron-openvswitch-agent restart
    # service neutron-dhcp-agent restart
    # service neutron-metadata-agent restart
    # service neutron-l3-agent restart

7.3. Instalación de Neutron en los nodos de cómputo

Realizar estos pasos en cada uno de los nodos de cómputo

  1. Configurar el kernel para desactivar el reverse path filtering. Añadir estas líneas el archivo /etc/sysctl.conf

    net.ipv4.conf.all.rp_filter=0
    net.ipv4.conf.default.rp_filter=0
  2. Cargar la nueva configuración del kernel

    # sysctl -p
  3. Instalar Neutron

    # apt install neutron-openvswitch-agent
  4. Configurar el archivo /etc/neutron/neutron.conf

    Este tutorial deja preparado el archivo /etc/neutron/neutron.conf para la instalación posterior del componente Neutron Load Balancer as a Service (LBaaS). En caso de no instalar tal componente habrá que eliminar la carga de LBaaS en la línea service_plugins del archivo /etc/neutron/neutron.conf. De no eliminar la referencia a LBaaS en /etc/neutron/neutron.conf el componente Neutron no funcionará correctamente.

    El archivo /etc/neutron/neutron.conf
    [DEFAULT]
    
    auth_strategy = keystone
    
    core_plugin = ml2
    
    service_plugins = router,neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2 (1)
    # Sustituir la línea anterior por la línea siguiente si no se va a instalar el componente de Load Balancer as a Service
    # service_plugins = router
    
    allow_overlapping_ips = true
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (2)
    
    notify_nova_on_port_status_changes = true
    
    notify_nova_on_port_data_changes = true
    
    dhcp_agents_per_network = 1
    
    [agent]
    
    root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    connection = mysql+pymysql://neutron:{{ neutron_dbpass }}@{{ nodes.controller.name }}/neutron (3)
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (4)
    auth_url = http://{{ nodes.controller.name }}:35357 (5)
    memcached_servers = {{ nodes.controller.name }}:11211 (6)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = neutron
    password = {{ neutron_dbpass }} (7)
    
    [matchmaker_redis]
    
    [nova]
    
    auth_url = http://{{ nodes.controller.name }}:35357 (8)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    region_name = {{ region }} (9)
    project_name = service
    username = nova
    password = {{ nova_dbpass }} (10)
    
    [oslo_concurrency]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    driver = messagingv2
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [qos]
    
    [quotas]
    
    [ssl]
    1 Sustituir la línea de service_plugins si no se va a instalar el componente Neutron Load Balancer as a Service (LBaaS)
    2 Contraseña de RabbitMQ y nombre del nodo de control
    3 Contraseña de Neutron y nombre del nodo de control
    4 Nombre del nodo de control
    5 Nombre del nodo de control
    6 Nombre del nodo de control
    7 Contraseña de Neutron
    8 Nombre del nodo de control
    9 Nombre de la región (p.e. RegionOne)
    10 Contraseña de Nova
  5. Configurar el archivo /etc/neutron/plugins/ml2/openvswitch_agent.ini

    El archivo /etc/neutron/plugins/ml2/openvswitch_agent.ini
    [ovs]
    integration_bridge = br-int
    
    int_peer_patch_port = patch-tun
    
    local_ip = {{ ansible_eth0.ipv4.address }} (1)
    
    bridge_mappings = provider:br-ex
    
    [agent]
    
    polling_interval = 15
    
    tunnel_types = vxlan
    
    l2_population = True
    
    arp_responder = False
    
    enable_distributed_routing = False
    
    [securitygroup]
    firewall_driver = iptables_hybrid
    
    enable_security_group = True
    1 IP de mantenimiento del nodo de cómputo
  6. Reiniciar el agente OpenvSwitch

    # service neutron-openvswitch-agent restart

7.4. Configuración de la red

Realizar estas operaciones en el nodo de control.

  1. Crear la red externa

    # openstack network create  --share --external --provider-physical-network provider --provider-network-type flat {{network_name}} (1)
    1 Nombre de la red externa
  2. Crear la subred de la red externa

# openstack subnet create --network {{network_name}} \ (1)
    --allocation-pool start={{allocation_pool_start}},end={{allocation_pool_end}} \ (2)
    --dns-nameserver {{dns_name_servers}} \ (3)
    --gateway {{provider_gateway}} \ (4)
    --subnet-range {{subnet_range}} \ (5)
    {{subnet_name}} (6)
1 Nombre de la red externa
2 Direcciones IP inicial y final del pool de direcciones asignadas
3 IP de servidores DNS
4 Gateway de la red externa
5 Nombre de la subred

8. Horizon

Realizar estos pasos en el nodo de control.

  1. Instalar Neutron

    # apt install openstack-dashboard
  2. Configurar el archivo /etc/openstack-dashboard/local_settings.py

    El archivo /etc/openstack-dashboard/local_settings.py
    import os
    
    from django.utils.translation import ugettext_lazy as _
    
    from horizon.utils import secret_key
    
    from openstack_dashboard.settings import HORIZON_CONFIG
    
    DEBUG = False
    
    WEBROOT = '/'
    
    ALLOWED_HOSTS = ['*']
    
    OPENSTACK_API_VERSIONS = {
        "identity": 3,
        "image": 2,
        "volume": 2,
    }
    
    OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
    
    OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default'
    
    LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))
    
    SECRET_KEY = secret_key.generate_or_read_from_file('/var/lib/openstack-dashboard/secret_key')
    
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
    
    CACHES = {
        'default': {
             'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
             'LOCATION': '{{ nodes.controller.name }}:11211', (1)
        }
    }
    
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    
    OPENSTACK_HOST = "{{ nodes.controller.name }}" (2)
    OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST
    
    OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user"
    
    OPENSTACK_KEYSTONE_BACKEND = {
        'name': 'native',
        'can_edit_user': True,
        'can_edit_group': True,
        'can_edit_project': True,
        'can_edit_domain': True,
        'can_edit_role': True,
    }
    
    OPENSTACK_HYPERVISOR_FEATURES = {
        'can_set_mount_point': False,
        'can_set_password': False,
        'requires_keypair': False,
        'enable_quotas': True
    }
    
    OPENSTACK_CINDER_FEATURES = {
        'enable_backup': False,
    }
    
    OPENSTACK_NEUTRON_NETWORK = {
        'enable_router': True,
        'enable_quotas': True,
        'enable_ipv6': True,
        'enable_distributed_router': False,
        'enable_ha_router': False,
        'enable_lb': True,
        'enable_firewall': True,
        'enable_vpn': True,
        'enable_fip_topology_check': True,
    
        # Default dns servers you would like to use when a subnet is
        # created.  This is only a default, users can still choose a different
        # list of dns servers when creating a new subnet.
        # The entries below are examples only, and are not appropriate for
        # real deployments
        # 'default_dns_nameservers': ["8.8.8.8", "8.8.4.4", "208.67.222.222"],
    
        # The profile_support option is used to detect if an external router can be
        # configured via the dashboard. When using specific plugins the
        # profile_support can be turned on if needed.
        'profile_support': None,
        #'profile_support': 'cisco',
    
        # Set which provider network types are supported. Only the network types
        # in this list will be available to choose from when creating a network.
        # Network types include local, flat, vlan, gre, vxlan and geneve.
        # 'supported_provider_types': ['*'],
    
        # You can configure available segmentation ID range per network type
        # in your deployment.
        # 'segmentation_id_range': {
        #     'vlan': [1024, 2048],
        #     'vxlan': [4094, 65536],
        # },
    
        # You can define additional provider network types here.
        # 'extra_provider_types': {
        #     'awesome_type': {
        #         'display_name': 'Awesome New Type',
        #         'require_physical_network': False,
        #         'require_segmentation_id': True,
        #     }
        # },
    
        # Set which VNIC types are supported for port binding. Only the VNIC
        # types in this list will be available to choose from when creating a
        # port.
        # VNIC types include 'normal', 'macvtap' and 'direct'.
        # Set to empty list or None to disable VNIC type selection.
        'supported_vnic_types': ['*'],
    }
    
    OPENSTACK_HEAT_STACK = {
        'enable_user_pass': True,
    }
    
    IMAGE_CUSTOM_PROPERTY_TITLES = {
        "architecture": _("Architecture"),
        "kernel_id": _("Kernel ID"),
        "ramdisk_id": _("Ramdisk ID"),
        "image_state": _("Euca2ools state"),
        "project_id": _("Project ID"),
        "image_type": _("Image Type"),
    }
    
    IMAGE_RESERVED_CUSTOM_PROPERTIES = []
    
    API_RESULT_LIMIT = 1000
    API_RESULT_PAGE_SIZE = 20
    
    SWIFT_FILE_TRANSFER_CHUNK_SIZE = 512 * 1024
    
    INSTANCE_LOG_LENGTH = 35
    
    DROPDOWN_MAX_ITEMS = 30
    
    TIME_ZONE = "Europe/Madrid"
    
    AVAILABLE_THEMES = [
        ('default', 'Default', 'themes/default'),
        ('material', 'Material', 'themes/material'),
    ]
    
    LOGGING = {
        'version': 1,
        # When set to True this will disable all logging except
        # for loggers specified in this configuration dictionary. Note that
        # if nothing is specified here and disable_existing_loggers is True,
        # django.db.backends will still log unless it is disabled explicitly.
        'disable_existing_loggers': False,
        'formatters': {
            'operation': {
                # The format of "%(message)s" is defined by
                # OPERATION_LOG_OPTIONS['format']
                'format': '%(asctime)s %(message)s'
            },
        },
        'handlers': {
            'null': {
                'level': 'DEBUG',
                'class': 'logging.NullHandler',
            },
            'console': {
                # Set the level to "DEBUG" for verbose output logging.
                'level': 'INFO',
                'class': 'logging.StreamHandler',
            },
            'operation': {
                'level': 'INFO',
                'class': 'logging.StreamHandler',
                'formatter': 'operation',
            },
        },
        'loggers': {
            # Logging from django.db.backends is VERY verbose, send to null
            # by default.
            'django.db.backends': {
                'handlers': ['null'],
                'propagate': False,
            },
            'requests': {
                'handlers': ['null'],
                'propagate': False,
            },
            'horizon': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'horizon.operation_log': {
                'handlers': ['operation'],
                'level': 'INFO',
                'propagate': False,
            },
            'openstack_dashboard': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'novaclient': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'cinderclient': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'keystoneclient': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'glanceclient': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'neutronclient': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'heatclient': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'swiftclient': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'openstack_auth': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'nose.plugins.manager': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'django': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'iso8601': {
                'handlers': ['null'],
                'propagate': False,
            },
            'scss': {
                'handlers': ['null'],
                'propagate': False,
            },
        },
    }
    
    SECURITY_GROUP_RULES = {
        'all_tcp': {
            'name': _('All TCP'),
            'ip_protocol': 'tcp',
            'from_port': '1',
            'to_port': '65535',
        },
        'all_udp': {
            'name': _('All UDP'),
            'ip_protocol': 'udp',
            'from_port': '1',
            'to_port': '65535',
        },
        'all_icmp': {
            'name': _('All ICMP'),
            'ip_protocol': 'icmp',
            'from_port': '-1',
            'to_port': '-1',
        },
        'ssh': {
            'name': 'SSH',
            'ip_protocol': 'tcp',
            'from_port': '22',
            'to_port': '22',
        },
        'smtp': {
            'name': 'SMTP',
            'ip_protocol': 'tcp',
            'from_port': '25',
            'to_port': '25',
        },
        'dns': {
            'name': 'DNS',
            'ip_protocol': 'tcp',
            'from_port': '53',
            'to_port': '53',
        },
        'http': {
            'name': 'HTTP',
            'ip_protocol': 'tcp',
            'from_port': '80',
            'to_port': '80',
        },
        'pop3': {
            'name': 'POP3',
            'ip_protocol': 'tcp',
            'from_port': '110',
            'to_port': '110',
        },
        'imap': {
            'name': 'IMAP',
            'ip_protocol': 'tcp',
            'from_port': '143',
            'to_port': '143',
        },
        'ldap': {
            'name': 'LDAP',
            'ip_protocol': 'tcp',
            'from_port': '389',
            'to_port': '389',
        },
        'https': {
            'name': 'HTTPS',
            'ip_protocol': 'tcp',
            'from_port': '443',
            'to_port': '443',
        },
        'smtps': {
            'name': 'SMTPS',
            'ip_protocol': 'tcp',
            'from_port': '465',
            'to_port': '465',
        },
        'imaps': {
            'name': 'IMAPS',
            'ip_protocol': 'tcp',
            'from_port': '993',
            'to_port': '993',
        },
        'pop3s': {
            'name': 'POP3S',
            'ip_protocol': 'tcp',
            'from_port': '995',
            'to_port': '995',
        },
        'ms_sql': {
            'name': 'MS SQL',
            'ip_protocol': 'tcp',
            'from_port': '1433',
            'to_port': '1433',
        },
        'mysql': {
            'name': 'MYSQL',
            'ip_protocol': 'tcp',
            'from_port': '3306',
            'to_port': '3306',
        },
        'rdp': {
            'name': 'RDP',
            'ip_protocol': 'tcp',
            'from_port': '3389',
            'to_port': '3389',
        },
    }
    
    REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES',
                                  'LAUNCH_INSTANCE_DEFAULTS',
                                  'OPENSTACK_IMAGE_FORMATS',
                                  'OPENSTACK_KEYSTONE_DEFAULT_DOMAIN']
    
     # The default theme if no cookie is present
    DEFAULT_THEME = 'default'
    
    WEBROOT='/horizon/'
    
    ALLOWED_HOSTS = '*'
    
    COMPRESS_OFFLINE = True
    
    ALLOWED_PRIVATE_SUBNET_CIDR = {'ipv4': [], 'ipv6': []}
    1 Nombre del nodo de control
    2 Nombre del nodo de control
  3. Reiniciar Apache y Memcached

    # service apache2 reload
    # service apache2 restart
    # service memcached restart

9. Neutron LBaaS

9.1. Instalación de Neutron LBaaS en el nodo de control

Realizar estos pasos en el nodo de control.

  1. Instalar python-neutron-lbaas

    # apt install python-neutron-lbaas
  2. Configurar el archivo /etc/neutron/neutron_lbaas.conf

    El archivo /etc/neutron/neutron_lbaas.conf
    [DEFAULT]
    
    [certificates]
    
    [quotas]
    
    [service_auth]
    
    [service_providers]
    
    service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
  3. Realizar la migración de la base de datos neutron-lbaas

    # su -s /bin/sh -c "neutron-db-manage --subproject neutron-lbaas upgrade head"
  4. Reiniciar Neutron neutron-server

    # service neutron-server restart
  5. Clonar el repositorio de neutron-lbaas

    # git clone https://git.openstack.org/openstack/neutron-lbaas-dashboard /tmp/neutron-lbaas-dashboard

    Neutron LBaaS no tiene empaquetada la integración con Horizon. En estos casos descargaremos los fuentes del dashboard, los procesaremos y los integraremos en Horizon.

  6. Instalar el dashboard de Neutron LBaaS desde /tmp/neutron-lbaas-dashboard/

    # cd /tmp/neutron-lbaas-dashboard/
    # python setup.py install
  7. Copiar los archivos del dashboard de Neutron LBaaS

    # cp /tmp/neutron-lbaas-dashboard/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py /usr/share/openstack-dashboard/openstack_dashboard/enabled/
  8. Instalar el módulo pexpect con pip

    pip install pexpect
  9. Realizar estos últimos pasos para terminar de integrar el dashboard en Horizon

    # cd /usr/share/openstack-dashboard
    # python manage.py collectstatic (1)
    # python manage.py compress
    1 Responder yes a la pregunta
  10. Reiniciar el servidor Apache

    # service apache2 restart

9.2. Instalación de Neutron LBaaS en el nodo de red

Realizar estos pasos en el nodo de red.

  1. Instalar neutron-lbaasv2-agent

    # apt install neutron-lbaasv2-agent
  2. Configurar el archivo /etc/neutron/lbaas_agent.ini

    El archivo /etc/neutron/lbaas_agent.ini
    [DEFAULT]
    
    device_driver = neutron_lbaas.drivers.haproxy.namespace_driver.HaproxyNSDriver
    interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
    
    [haproxy]
    user_group = haproxy
  3. Configurar el archivo /etc/neutron/neutron_lbaas.conf

    El archivo /etc/neutron/neutron_lbaas.conf
    [DEFAULT]
    
    [certificates]
    
    [quotas]
    
    [service_auth]
    
    [service_providers]
    
    service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
  4. Reiniciar el servicio neutron-lbaasv2-agent

    # service neutron-lbaasv2-agent restart

10. Cinder

Realizar estar operaciones en el nodo de control.

La instalación de Cinder descrita en este tutorial hace uso de un NAS como dispositivo de almacenamiento de volúmenes. Cinder mantiene una serie de dispositivos compatibles y que disponen de drivers para poder funcionar como nodo de almacenamiento. Esto permite contar con un nodo de almacenamiento a un coste menor que un servidor dedicado. Los paquetes y archivos de configuración quedan instalados en el nodo de control.

  1. Creación y configuración de la base de datos cinder

    MariaDB [(none)]> CREATE DATABASE cinder;
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' \
      IDENTIFIED BY 'CINDER_DBPASS'; (1)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' \
      IDENTIFIED BY 'CINDER_DBPASS'; (2)
    1 Contraseña del usuario Cinder
    2 Contraseña del usuario Cinder
  2. Realizar la configuración de Cinder (usuario cinder, añadir el usuario cinder al proyecto service con el rol admin y crear los servicios cinder, cinderv2 y cinderv3).

    # source openrc-admin (1)
    
    # openstack user create --domain default cinder --password {{ cinder_dbpass }} (2)
    # openstack role add --project service --user cinder admin
    # openstack service create --name cinder --description "OpenStack Block Storage" volume
    # openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2
    # openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3
    1 Credenciales del usuario cinder
  3. Crear los endpoints de la API

    # openstack endpoint create --region {{region}} cinder public http://{{ nodes_by_name.controller.provider_ip }}:8776/v1/%(project_id)s (1)
    # openstack endpoint create --region {{region}} cinder internal http://{{ nodes_by_name.controller.tunnel_ip }}:8776/v1/%(project_id)s (2)
    # openstack endpoint create --region {{region}} cinder admin http://{{ nodes_by_name.controller.management_ip }}:8776/v1/%(project_id)s (3)
    
    # openstack endpoint create --region {{region}} cinderv2 public http://{{ nodes_by_name.controller.provider_ip }}:8776/v2/%(project_id)s (4)
    # openstack endpoint create --region {{region}} cinderv2 internal http://{{ nodes_by_name.controller.tunnel_ip }}:8776/v2/%(project_id)s (5)
    # openstack endpoint create --region {{region}} cinderv3 admin http://{{ nodes_by_name.controller.management_ip }}:8776/v2/%(project_id)s (6)
    
    # openstack endpoint create --region {{region}} cinderv3 public http://{{ nodes_by_name.controller.provider_ip }}:8776/v3/%(project_id)s (7)
    # openstack endpoint create --region {{region}} cinderv3 internal http://{{ nodes_by_name.controller.tunnel_ip }}:8776/v3/%(project_id)s (8)
    # openstack endpoint create --region {{region}} cinderv3 admin http://{{ nodes_by_name.controller.management_ip }}:8776/v3/%(project_id)s (9)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
    4 Región (p.e, RegionOne) e IP externa del nodo de control
    5 Región (p.e, RegionOne) e IP de túnel del nodo de control
    6 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
    7 Región (p.e, RegionOne) e IP externa del nodo de control
    8 Región (p.e, RegionOne) e IP de túnel del nodo de control
    9 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  4. Instalar los paquetes de Cinder

    # apt install cinder-api cinder-scheduler
  5. Configurar el archivo /etc/cinder/cinder.conf

    El archivo /etc/cinder/cinder.conf
    [DEFAULT]
    my_ip = {{ nodes.controller.management_ip }} (1)
    glance_api_servers = http://{{ nodes.controller.name }}:9292 (2)
    auth_strategy = keystone
    enabled_backends = ds1515pV1 (3)
    iscsi_helper = tgtadm
    iscsi_protocol = iscsi
    rpc_backends = rabbit
    
    rabbit_durable_queues = true
    
    [BACKEND]
    [BRCD_FABRIC_EXAMPLE]
    [CISCO_FABRIC_EXAMPLE]
    [COORDINATION]
    [FC-ZONE-MANAGER]
    [KEY_MANAGER]
    [barbican]
    [cors]
    [cors.subdomain]
    [database]
    connection = mysql+pymysql://cinder:{{cinder_dbpass}}@{{ nodes.controller.name }}/cinder (4)
    [key_manager]
    [keystone_authtoken]
    auth_uri = http://{{ nodes.controller.name }}:5000 (5)
    auth_url = http://{{ nodes.controller.name }}:35357 (6)
    memcached_servers = {{ nodes.controller.name }}:11211 (7)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = cinder
    password = {{ cinder_dbpass}} (8)
    [matchmaker_redis]
    [oslo_concurrency]
    lock_path = /var/lock/cinder
    [oslo_messaging_amqp]
    [oslo_messaging_notifications]
    driver = messagingv2
    [oslo_messaging_rabbit]
    rabbit_host = {{ nodes.controller.name }} (9)
    rabbit_userid = openstack
    rabbit_password = {{RABBIT_PASS}} (10)
    [oslo_messaging_zmq]
    [oslo_middleware]
    [oslo_policy]
    [oslo_reports]
    [oslo_versionedobjects]
    [ssl]
    
    [ds1515pV1] (11)
    volume_backend_name = {{ nas_backend_name }} (12)
    volume_driver = cinder.volume.drivers.synology.synology_iscsi.SynoISCSIDriver
    iscs_protocol = iscsi
    iscsi_ip_address = {{ nas_private_ip }} (13)
    synology_admin_port = {{nas_port}} (14)
    synology_username = {{nas_user}} (15)
    synology_password = {{nas_password}} (16)
    synology_pool_name = {{nas_volume}} (17)
    1 IP de mantenimiento del nodo de control
    2 Nombre del nodo de control
    3 Salto a etiqueta personalizada de configuración del NAS para almacenamiento de los volúmenes
    4 Contraseña de Cinder y nombre del nodo de control
    5 Nombre del nodo de control
    6 Nombre del nodo de control
    7 Nombre del nodo de control
    8 Contraseña de Cinder
    9 Nombre del nodo de control
    10 Contraseña de RabbitMQ
    11 Etiqueta de bloque personalizada para la configuración del NAS
    12 Nombre que se da al tipo de volúmenes del NAS en Horizon
    13 IP de mantenimiento del NAS
    14 Puerto de acceso al NAS
    15 Usuario del NAS
    16 Contraseña del usuario del NAS
    17 Nombre del volumen usado en el NAS
  6. Inicializar la base de datos cinder

    # su -s /bin/sh -c "cinder-manage db sync" cinder
  7. Reiniciar los servicios cinder-scheduler y Apache

    # service cinder-scheduler restart
    # service apache2 restart
  8. Instalar LVM y cinder-volume

    # apt install lvm2
    # apt install cinder-volume
  9. Reiniciar los servicios tgt y cinder-volume

    # service tgt restart
    # service cinder-volume restart
  10. Crear el tipo de volumen para el NAS

    # openstack volume type create --public {{ nas_volume_type_name }} (1)
    # openstack volume type set --property volume_backend_name={{ nas_backend_name }} {{ nas_volume_type_name }} (2)
    1 Tipo de volumen (p.e. NAS)
    2 Nombre asignado al tipo de volumen (p.e. VOL_NAS)

11. Heat

La instalación de Heat se realiza en el nodo de control.

  1. Creación y configuración de la base de datos heat

    CREATE DATABASE heat;
    
    GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'localhost' \
      IDENTIFIED BY 'HEAT_DBPASS'; (1)
    GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'%' \
      IDENTIFIED BY 'HEAT_DBPASS'; (2)
    1 Contraseña del usuario Heat
    2 Contraseña del usuario Heat
  2. Realizar la configuración de Heat (usuario heat, añadir el usuario heat al proyecto service con el rol admin y crear los servicios heat y heat-cfn)

    # source openrc-admin (1)
    
    # openstack user create --domain default heat --password {{ heat_dbpass }} (2)
    # openstack role add --project service --user heat admin
    # openstack service create --name heat --description "Orchestration" orchestration
    # openstack service create --name heat-cfn --description "Orchestration" cloudformation
  3. Crear los endpoints de la API

    # openstack endpoint create --region {{region}} orchestration public http://{{ nodes_by_name.controller.provider_ip }}:8004/v1/%(tenant_id)s (1)
    # openstack endpoint create --region {{region}} orchestration internal http://{{ nodes_by_name.controller.tunnel_ip }}:8004/v1/%(tenant_id)s (2)
    # openstack endpoint create --region {{region}} orchestration admin http://{{ nodes_by_name.controller.management_ip }}:8004/v1/%(tenant_id)s (3)
    
    # openstack endpoint create --region {{region}} cloudformation public http://{{ nodes_by_name.controller.provider_ip }}:8000/v1 (4)
    # openstack endpoint create --region {{region}} cloudformation internal http://{{ nodes_by_name.controller.tunnel_ip }}:8000/v1 (5)
    # openstack endpoint create --region {{region}} cloudformation admin http://{{ nodes_by_name.controller.management_ip }}:8000/v1 (6)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
    4 Región (p.e, RegionOne) e IP externa del nodo de control
    5 Región (p.e, RegionOne) e IP de túnel del nodo de control
    6 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  4. Crear roles, dominio y usuario en el dominio necesarios para Heat

    # openstack domain create --description "Stack projects and users" heat
    # openstack user create --domain heat --password {{heat_dbpass}} heat_domain_admin
    # openstack role add --domain heat --user-domain heat --user heat_domain_admin admin
    # openstack role create heat_stack_owner
    # openstack role add --project demo --user demo heat_stack_owner
    # openstack role create heat_stack_user
  5. Instalar los paquetes de Heat

    # apt install heat-api heat-api-cfn heat-engine
  6. Configurar el archivo /etc/heat/heat.conf

    El archivo /etc/heat/heat.conf
    [DEFAULT]
    
    heat_metadata_server_url = http://{{ nodes.controller.name }}:8000 (1)
    
    heat_waitcondition_server_url = http://{{ nodes.controller.name }}:8000/v1/waitcondition (2)
    
    stack_user_domain_name = heat
    
    stack_domain_admin = heat_domain_admin
    
    stack_domain_admin_password = {{ heat_dbpass }} (3)
    
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (4)
    
    [auth_password]
    
    [clients]
    
    [clients_aodh]
    
    [clients_barbican]
    
    [clients_ceilometer]
    
    [clients_cinder]
    
    [clients_designate]
    
    [clients_glance]
    
    [clients_heat]
    
    [clients_keystone]
    
    auth_uri =  http://{{ nodes.controller.name }}:35357 (5)
    
    [clients_magnum]
    
    [clients_manila]
    
    [clients_mistral]
    
    [clients_monasca]
    
    [clients_neutron]
    
    [clients_nova]
    
    [clients_sahara]
    
    [clients_senlin]
    
    [clients_swift]
    
    [clients_trove]
    
    [clients_zaqar]
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    connection = mysql+pymysql://heat:{{ heat_dbpass }}@{{ nodes.controller.name }}/heat (6)
    
    [ec2authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (7)
    
    [eventlet_opts]
    
    [healthcheck]
    
    [heat_api]
    
    [heat_api_cfn]
    
    [heat_api_cloudwatch]
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (8)
    auth_url = http://{{ nodes.controller.name }}:35357 (9)
    memcached_servers = {{ nodes.controller.name }}:11211 (10)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = heat
    password = {{ heat_dbpass}} (11)
    
    [matchmaker_redis]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    driver = messagingv2
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_policy]
    
    [paste_deploy]
    
    [profiler]
    
    [revision]
    
    [ssl]
    
    [trustee]
    
    auth_type = password
    
    auth_url = http://{{ nodes.controller.name }}:35357 (12)
    
    username = heat
    
    user_domain_name = default
    
    password = {{ heat_dbpass }} (13)
    
    [volumes]
    1 Nombre del nodo de control
    2 Nombre del nodo de control
    3 Contraseña de Heat
    4 Contraseña de RabbitMQ y nombre del nodo de control
    5 Nombre del nodo de control
    6 Contraseña de Cinder y nombre del nodo de control
    7 Nombre del nodo de control
    8 Nombre del nodo de control
    9 Nombre del nodo de control
    10 Nombre del nodo de control
    11 Contraseña de Heat
    12 Nombre del nodo de control
    13 Contraseña de Heat
  7. Inicializar la base de datos heat

    su -s /bin/sh -c "heat-manage db_sync" heat
  8. Reiniciar servicios de Heat

    # service heat-api restart
    # service heat-api-cfn restart
    # service heat-engine restart

12. Manila

12.1. Instalación de Manila en el nodo de control

Realizar estos pasos en el nodo de control

  1. Creación y configuración de la base de datos manila

    CREATE DATABASE manila;
    
    GRANT ALL PRIVILEGES ON manila.* TO 'manila'@'localhost' \
      IDENTIFIED BY 'MANILA_DBPASS'; (1)
    GRANT ALL PRIVILEGES ON manila.* TO 'manila'@'%' \
      IDENTIFIED BY 'MANILA_DBPASS'; (2)
    1 Contraseña de Manila
    2 Contraseña de Manila
  2. Realizar la configuración de Manila (usuario manila, añadir el usuario manila al proyecto service con el rol admin y crear los servicios manila y manilav2).

    # source openrc-admin (1)
    
    # openstack user create --domain default manila --password {{ manila_dbpass }}
    # openstack role add --project service --user manila admin
    # openstack service create --name manila --description "OpenStack Shared File Systems" share
    # openstack service create --name manilav2 --description "OpenStack Shared File Systems" sharev2
    1 Credenciales del usuario manila
  3. Crear los endpoints de la API

    # openstack endpoint create --region {{region}} share public http://{{ nodes_by_name.controller.provider_ip }}:8786/v1/%\(tenant_id\)s (1)
    # openstack endpoint create --region {{region}} share internal http://{{ nodes_by_name.controller.tunnel_ip }}:8786/v1/%\(tenant_id\)s (2)
    # openstack endpoint create --region {{region}} share admin http://{{ nodes_by_name.controller.management_ip }}:8786/v1/%\(tenant_id\)s (3)
    
    # openstack endpoint create --region {{region}} sharev2 public http://{{ nodes_by_name.controller.provider_ip }}:8786/v2/%\(tenant_id\)s (4)
    # openstack endpoint create --region {{region}} sharev2 internal http://{{ nodes_by_name.controller.tunnel_ip }}:8786/v2/%\(tenant_id\)s (5)
    # command: openstack endpoint create --region {{region}} sharev2 admin http://{{ nodes_by_name.controller.management_ip }}:8786/v2/%\(tenant_id\)s (6)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
    4 Región (p.e, RegionOne) e IP externa del nodo de control
    5 Región (p.e, RegionOne) e IP de túnel del nodo de control
    6 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  4. Instalar los paquetes de Cinder

    # apt install manila-api manila-scheduler python-manilaclient
  5. Configurar el archivo /etc/manila/manila.conf

    El archivo /etc/manila/manila.conf
    [DEFAULT]
    
    rpc_backend = rabbit
    rabbit_durable_queues = true
    
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (1)
    
    default_share_type = default_share_type
    share_name_template = share-%s
    rootwrap_config = /etc/manila/rootwrap.conf
    api_paste_config = /etc/manila/api-paste.ini
    
    auth_strategy = keystone
    
    my_ip = {{ nodes.controller.management_ip }} (2)
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    connection = mysql+pymysql://manila:{{ manila_dbpass }}@{{ nodes.controller.management_ip }}/manila (3)
    
    [keystone_authtoken]
    
    memcached_servers = {{ nodes.controller.management_ip }}:11211 (4)
    auth_uri = http://{{ nodes.controller.management_ip }}:5000 (5)
    auth_url = http://{{ nodes.controller.management_ip }}:35357 (6)
    auth_type = password
    project_domain_id = default
    user_domain_id = default
    project_name = service
    username = manila
    password = {{ manila_dbpass }} (7)
    
    [matchmaker_redis]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_concurrency]
    lock_path = /var/lib/manila/tmp
    1 Contraseña de RabbitMQ y nombre del nodo de control
    2 Nombre del nodo de control
    3 Contraseña de Manila y nombre del nodo de control
    4 Nombre del nodo de control
    5 Nombre del nodo de control
    6 Nombre del nodo de control
    7 Contraseña de Manila
  6. Inicializar la base de datos manila

    # su -s /bin/sh -c "manila-manage db sync" manila
  7. Reiniciar servicios de Manila

    # service manila-scheduler restart
    # service manila-api restart
  8. Eliminar la base de datos manila.sqlite

    # rm -f /var/lib/manila/manila.sqlite
  9. Clonar el repositorio de manila-ui

    # git clone https://github.com/openstack/manila-ui /tmp/manila-ui

    Manila no tiene empaquetada la integración con Horizon. En estos casos descargaremos los fuentes del dashboard, los procesaremos y los integraremos en Horizon.

  10. Instalar el dashboard de Manila desde /tmp/manila-ui/

    # cd /tmp/manila-ui/
    # python setup.py install
  11. Copiar los archivos del dashboard de Manila

    # cp /tmp/manila-ui/manila_ui/local/enabled/_90_manila*  /usr/share/openstack-dashboard/openstack_dashboard/local/enabled/
  12. Realizar estos últimos pasos para terminar de integrar el dashboard en Horizon

    # cd /usr/share/openstack-dashboard
    # python manage.py collectstatic (1)
    # python manage.py compress
    1 Responder yes a la pregunta
  13. Reiniciar el servidor Apache

    # service apache2 restart

12.2. Instalación de Manila en el nodo de almacenamiento compartido

Realizar estos pasos en el nodo de almacenamiento compartido

  1. Instalar Manila en el nodo de almacenamiento compartido

    # apt install manila-share python-pymysql lvm2 nfs-kernel-server
  2. Configurar el archivo /etc/manila/manila.conf

    El archivo /etc/manila/manila.conf
    [DEFAULT]
    
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.management_ip }} (1)
    default_share_type = default_share_type
    rootwrap_config = /etc/manila/rootwrap.conf
    auth_strategy = keystone
    my_ip = {{ nodes_by_name.shared.management_ip }} (2)
    enabled_share_backends = lvm
    enabled_share_protocols = NFS
    rpc_backend = rabbit
    rabbit_durable_queues = true
    api_paste_config = /etc/manila/api-paste.ini
    state_path = /var/lib/manila
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    connection = mysql+pymysql://manila:{{ manila_dbpass }}@{{ nodes.controller.management_ip }}/manila (3)
    
    [keystone_authtoken]
    
    memcached_servers = {{nodes.controller.management_ip }}:11211 (4)
    auth_uri = http://{{ nodes.controller.management_ip }}:5000 (5)
    auth_url = http://{{ nodes.controller.management_ip }}:35357 (6)
    auth_type = password
    project_domain_id = default
    user_domain_id = default
    project_name = service
    username = manila
    password = {{ manila_dbpass }} (7)
    
    [matchmaker_redis]
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_middleware]
    
    [oslo_concurrency]
    lock_path = /var/lib/manila/tmp
    
    [lvm]
    share_backend_name = LVM
    share_driver = manila.share.drivers.lvm.LVMShareDriver
    driver_handles_share_servers = False
    lvm_share_volume_group = manila-volumes
    lvm_share_export_ip = {{ nodes_by_name.shared.provider_ip }} (8)
    ---
    <1> Contraseña de RabbitMQ y dirección IP de mantenimiento del nodo de control
    <2> IP de mantenimiento del nodo de almacenamiento compartido
    <3> Contraseña de Manila y dirección IP de mantenimiento del nodo de control
    <4> IP de mantenemiento del nodo de control
    <5> IP de mantenemiento del nodo de control
    <6> IP de mantenemiento del nodo de control
    <7> Contraseña de Manila
    <8> IP externa del nodo de almacenamiento compartido
  3. Crear el volumen físico LVM

    # pvcreate /dev/{{ shared_storage_device }} (1)
    1 Volumen del nodo de almacenamiento compartido dedicado a Manila
  4. Crear el grupo de volúmenes manila-volumes

    # vgcreate manila-volumes /dev/{{ shared_storage_device }} (1)
    1 Volumen del nodo de almacenamiento compartido dedicado a Manila
  5. Configurar el archivo /etc/lvm/lvm.conf añadiendo la línea siguiente al bloque devices para especificar los dispositivos utilizados por LVM

    filter = [ "a/{{ shared_storage_device }}/", "r/.*/"] (1)
    1 Volumen del nodo de almacenamiento compartido dedicado a Manila
  6. Reiniciar el servicio manila-share

    # service manila-share restart
  7. Activar el servicio nfs-server

    # systemctl enable nfs-server
  8. Eliminar la base de dato manila.sqlite ` en el nodo de almacenamiento compartido.

    # rm -f /var/lib/manila/manila.sqlite

12.3. Configuración de Manila en el nodo de control

Realizar esta operación en el nodo de control.

  1. Crear el tipo para volúmenes compartidos con Shared File Systems del tipo DHSS = False

    # manila type-create default_share_type False

13. Swift

13.1. Instalación de Swift en el nodo de control

Realizar estas operaciones en el nodo de control.

  1. Realizar la configuración de Cinder (usuario cinder, añadir el usuario cinder al proyecto service con el rol admin y crear los servicios cinder, cinderv2 y cinderv3).

    # source openrc-admin (1)
    
    # openstack user create --domain default swift --password {{ swift_dbpass }} (2)
    # openstack role add --project service --user swift admin
    # openstack service create --name swift --description "OpenStack Object Storage" object-store
    1 Cargar las credenciales de admin
    2 Contraseña del usuario swift
  2. Crear los endpoints de la API

    # openstack endpoint create --region {{region}} object-store public http://{{ nodes_by_name.controller.provider_ip }}:8080/v1/AUTH_%\(tenant_id\)s (1)
    # openstack endpoint create --region {{region}} object-store internal http://{{ nodes_by_name.controller.tunnel_ip }}:8080/v1/AUTH_%\(tenant_id\)s (2)
    # openstack endpoint create --region {{region}} object-store admin http://{{ nodes_by_name.controller.management_ip }}:8080/v1/AUTH_%\(tenant_id\)s (3)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  3. Instalar los paquetes de Swift

    # apt install swift swift-proxy python-swiftclient python-keystoneclient python-keystonemiddleware
  4. Configurar el archivo /etc/swift/proxy-server.conf

    El archivo /etc/swift/proxy-server.conf
    [DEFAULT]
    bind_port = 8080
    swift_dir = /etc/swift
    user = swift
    
    [pipeline:main]
    pipeline = catch_errors gatekeeper healthcheck proxy-logging cache container_sync bulk ratelimit authtoken keystoneauth container-quotas account-quotas slo dlo versioned_writes proxy-logging proxy-server
    
    [app:proxy-server]
    use = egg:swift#proxy
    account_autocreate = True
    
    [filter:tempauth]
    use = egg:swift#tempauth
    
    user_admin_admin = admin .admin .reseller_admin
    user_test_tester = testing .admin
    user_test2_tester2 = testing2 .admin
    user_test_tester3 = testing3
    user_test5_tester5 = testing5 service
    
    [filter:authtoken]
    paste.filter_factory = keystonemiddleware.auth_token:filter_factory
    
    auth_uri = http://{{ nodes.controller.name }}:5000 (1)
    auth_url = http://{{ nodes.controller.name }}:35357 (2)
    memcached_servers = {{ nodes.controller.name }}:11211 (3)
    auth_type = password
    project_domain_name = default
    user_domain_name = default
    project_name = service
    username = swift
    password = {{ swift_dbpass}} (4)
    
    delay_auth_decision = True
    [filter:keystoneauth]
    use = egg:swift#keystoneauth
    operator_roles = admin, user
    
    [filter:healthcheck]
    use = egg:swift#healthcheck
    
    [filter:cache]
    use = egg:swift#memcache
    memcache_servers = {{ nodes.controller.name }}:11211 (5)
    
    [filter:ratelimit]
    use = egg:swift#ratelimit
    
    [filter:domain_remap]
    use = egg:swift#domain_remap
    
    [filter:catch_errors]
    use = egg:swift#catch_errors
    
    [filter:cname_lookup]
    use = egg:swift#cname_lookup
    
    [filter:staticweb]
    use = egg:swift#staticweb
    
    [filter:tempurl]
    use = egg:swift#tempurl
    
    [filter:formpost]
    use = egg:swift#formpost
    
    [filter:name_check]
    use = egg:swift#name_check
    
    [filter:list-endpoints]
    use = egg:swift#list_endpoints
    
    [filter:proxy-logging]
    use = egg:swift#proxy_logging
    
    [filter:bulk]
    use = egg:swift#bulk
    
    [filter:slo]
    use = egg:swift#slo
    
    [filter:dlo]
    use = egg:swift#dlo
    
    [filter:container-quotas]
    use = egg:swift#container_quotas
    
    [filter:account-quotas]
    use = egg:swift#account_quotas
    
    [filter:gatekeeper]
    use = egg:swift#gatekeeper
    
    [filter:container_sync]
    use = egg:swift#container_sync
    
    [filter:xprofile]
    use = egg:swift#xprofile
    
    [filter:versioned_writes]
    use = egg:swift#versioned_writes
    
    [filter:copy]
    use = egg:swift#copy
    
    [filter:keymaster]
    use = egg:swift#keymaster
    
    encryption_root_secret = changeme
    
    [filter:encryption]
    use = egg:swift#encryption
    
    [filter:ceilometer]
    paste.filter_factory = ceilometermiddleware.swift:filter_factory
    
    control_exchange = swift
    url = rabbit://openstack:{{ RABBIT_PASS }}@{{ short_controller_name }}:5672/ (6)
    driver = messagingv2
    topic = notifications
    log_level = WARN
    1 Nombre del nodo de control
    2 Nombre del nodo de control
    3 Nombre del nodo de control
    4 Contraseña de Swift
    5 Nombre del nodo de control
    6 Contraseña de RabbitMQ y nombre del nodo de control
  5. Cambiar el propietario del directorio /etc/swift

    # chown -R root:swift /etc/swift

13.2. Instalar Swift en nodos de almacenamiento de objetos

Realizar estas operaciones en los nodos de almacenamiento de objetos.

  1. Instalar los paquetes de soporte

    # apt install xfsprogs rsync
  2. Crear particiones

    # fdisk /dev/sdb
    # fdisk /dev/sdc

    En este tutorial suponemos que cada uno de los servidores dedicados a almacenamiento de objetos cuentan con 2 discos (sdb y sdc).

  3. Formatear discos en formato xfs

    # mkfs.xfs /dev/sdb1
    # mkfs.xfs /dev/sdc1
  4. Crear los puntos de montaje

    # mkdir -p /srv/node/sdb
    # mkdir -p /srv/node/sdc
  5. Montar los discos

    # mount /dev/sdb1 /srv/node/sdb
    # mount /dev/sdc1 /srv/node/sdc
  6. Configurar el archivo /etc/rsyncd.conf

    El archivo /etc/rsync.conf
    uid = swift
    gid = swift
    log file = /var/log/rsyncd.log
    pid file = /var/run/rsyncd.pid
    address = {{ ansible_eth0.ipv4.address }} (1)
    
    [account]
    max connections = 2
    path = /srv/node/
    read only = False
    lock file = /var/lock/account.lock
    
    [container]
    max connections = 2
    path = /srv/node/
    read only = False
    lock file = /var/lock/container.lock
    
    [object]
    max connections = 2
    path = /srv/node/
    read only = False
    lock file = /var/lock/object.lock
    1 IP de mantenimiento del nodo de almacenamiento de objetos
  7. Activar rsync en /etc/default/rsync

    RSYNC_ENABLE=true (1)
    1 Establecer este valor
  8. Iniciar rsync

    # service rsync start
  9. Instalar los paquetes de Swift en los nodos de almacenamiento de objetos

    # apt install swift swift-account swift-container swift-object
  10. Configurar el archivo /etc/swift/account-server.conf

    El archivo /etc/swift/account-server.conf
    [DEFAULT]
    bind_ip = {{ ansible_eth0.ipv4.address }} (1)
    bind_port = 6202
    user = swift
    swift_dir = /etc/swift
    devices = /srv/node
    mount_check = true
    
    [pipeline:main]
    pipeline = healthcheck recon account-server
    
    [app:account-server]
    use = egg:swift#account
    
    [filter:healthcheck]
    use = egg:swift#healthcheck
    
    [filter:recon]
    use = egg:swift#recon
    recon_cache_path = /var/cache/swift
    
    [account-replicator]
    
    [account-auditor]
    
    [account-reaper]
    
    [filter:xprofile]
    use = egg:swift#xprofile
    1 IP de mantenimiento del nodo de almacenamiento de objetos
  11. Configurar el archivo /etc/swift/container-server.conf

    El archivo /etc/swift/container-server.conf
    [DEFAULT]
    bind_ip = {{ ansible_eth0.ipv4.address }} (1)
    bind_port = 6201
    user = swift
    swift_dir = /etc/swift
    devices = /srv/node
    mount_check = true
    
    [pipeline:main]
    pipeline = healthcheck recon container-server
    
    [app:container-server]
    use = egg:swift#container
    
    [filter:healthcheck]
    use = egg:swift#healthcheck
    
    [filter:recon]
    use = egg:swift#recon
    recon_cache_path = /var/cache/swift
    
    [container-replicator]
    
    [container-updater]
    
    [container-auditor]
    
    [container-sync]
    
    [filter:xprofile]
    use = egg:swift#xprofile
    1 IP de mantenimiento del nodo de almacenamiento de objetos
  12. Configurar el archivo /etc/swift/object-server.conf

    El archivo /etc/swift/object-server.conf
    [DEFAULT]
    bind_ip = {{ ansible_eth0.ipv4.address }} (1)
    bind_port = 6200
    user = swift
    swift_dir = /etc/swift
    devices = /srv/node
    mount_check = true
    
    [pipeline:main]
    pipeline = healthcheck recon object-server
    
    [app:object-server]
    use = egg:swift#object
    
    [filter:healthcheck]
    use = egg:swift#healthcheck
    
    [filter:recon]
    use = egg:swift#recon
    recon_cache_path = /var/cache/swift
    recon_lock_path = /var/lock
    
    [object-replicator]
    
    [object-reconstructor]
    
    [object-updater]
    
    [object-auditor]
    
    [filter:xprofile]
    use = egg:swift#xprofile
    1 IP de mantenimiento del nodo de almacenamiento de objetos
  13. Crear el directorio /srv/node si no existe y cambiarlo de propietario

    # mkdir -p /srv/node
    # chown -R swift:swift /srv/node
  14. Crear el directorio /var/cache/swift si no existe y cambiarlo de propietario

    # mkdir -p /var/cache/swift
    # chown -R root:swift /var/cache/swift

13.3. Crear y distribuir los anillos iniciales

Realizar estas operaciones en el nodo de control.

  1. Crear el archivo base account.builder

    # swift-ring-builder account.builder create 10 3 1
  2. Añadir cada nodo de almacenamiento al anillo. Añade el anillo para la combinación de los dos nodos de almacenamiento de objetos (objetos01 y objetos02) con los dos dispositivos (sdb y sdc).

    # swift-ring-builder account.builder add --region 1 --zone 1 --ip {{ objetos01.management_ip}}  \ (1)
        --port 6202 --device {{ sdb }}  \ (2)
        --weight 100} (3)
    # swift-ring-builder account.builder add --region 1 --zone 1 --ip {{ objetos01.management_ip}}  \
        --port 6202 --device {{ sdc }} \
        --weight 100}
    
    # swift-ring-builder account.builder add --region 1 --zone 1 --ip {{ objetos02.management_ip}}  \
        --port 6202 --device {{ sdb }}  \
        --weight 100}
    # swift-ring-builder account.builder add --region 1 --zone 1 --ip {{ objetos02.management_ip}}  \
        --port 6202 --device {{ sdc }} \
        --weight 100}
    1 IP de mantenimiento del primer nodo de almacenamiento de objetos
    2 Primer dispositivo
    3 El peso lo inicializamos a 100
  3. Rebalancear el anillo

    # swift-ring-builder account.builder rebalance
  4. Crear el archivo base container.builder. Añade el anillo para la combinación de los dos nodos de almacenamiento de objetos (objetos01 y objetos02) con los dos dispositivos (sdb y sdc).

    swift-ring-builder container.builder create 10 3 1
  5. Añadir cada nodo de almacenamiento al anillo

    # swift-ring-builder container.builder add --region 1 --zone 1 --ip {{ objetos01.management_ip}}  \ (1)
        --port 6202 --device {{ sdb }}  \ (2)
        --weight 100} (3)
    # swift-ring-builder container.builder add --region 1 --zone 1 --ip {{ objetos01.management_ip}}  \
        --port 6202 --device {{ sdc }} \
        --weight 100}
    
    # swift-ring-builder container.builder add --region 1 --zone 1 --ip {{ objetos02.management_ip}}  \
        --port 6202 --device {{ sdb }}  \
        --weight 100}
    # swift-ring-builder container.builder add --region 1 --zone 1 --ip {{ objetos02.management_ip}}  \
        --port 6202 --device {{ sdc }} \
        --weight 100}
    1 IP de mantenimiento del primer nodo de almacenamiento de objetos
    2 Primer dispositivo
    3 El peso lo inicializamos a 100
  6. Rebalancear el anillo

    # swift-ring-builder container.builder rebalance
  7. Crear el archivo base object.builder

    # swift-ring-builder object.builder create 10 3 1
  8. Añadir cada nodo de almacenamiento al anillo

    # swift-ring-builder object.builder add --region 1 --zone 1 --ip {{ objetos01.management_ip}}  \ (1)
        --port 6202 --device {{ sdb }}  \ (2)
        --weight 100} (3)
    # swift-ring-builder object.builder add --region 1 --zone 1 --ip {{ objetos01.management_ip}}  \
        --port 6202 --device {{ sdc }} \
        --weight 100}
    
    # swift-ring-builder object.builder add --region 1 --zone 1 --ip {{ objetos02.management_ip}}  \
        --port 6202 --device {{ sdb }}  \
        --weight 100}
    # swift-ring-builder object.builder add --region 1 --zone 1 --ip {{ objetos02.management_ip}}  \
        --port 6202 --device {{ sdc }} \
        --weight 100}
    1 IP de mantenimiento del primer nodo de almacenamiento de objetos
    2 Primer dispositivo
    3 El peso lo inicializamos a 100
  9. Rebalancear el anillo

    # swift-ring-builder object.builder rebalance
  10. Distribuir los archivos de configuración del anillo a los nodos de almacenamiento de objetos

    # scp /etc/swift/*.ring.gz {{ objetos01.management_ip }}:/etc/swift (1)
    # scp /etc/swift/*.ring.gz {{ objetos02.management_ip }}:/etc/swift (2)
    1 IP de mantenimento del nodo 1 de almacenamiento de objetos
    2 IP de mantenimento del nodo 2 de almacenamiento de objetos

13.4. Modificar la configuración de Swift

Realizar estas operaciones en el nodo de control y en los nodos de almacenamiento de objetos

  1. Modificar el archivo /etc/swift/swift.conf

    El archivo /etc/swift/swift.conf
    [swift-hash]
    
    swift_hash_path_suffix = {{ hash_path_suffix }} (1)
    swift_hash_path_prefix = {{ hash_path_prefix }} (2)
    
    [storage-policy:0]
    name = Policy-0
    default = yes
    aliases = yellow, orange
    
    [swift-constraints]
    1 Prefijo secreto de hash
    2 Sufijo secreto de hash
  2. Cambiar el propietario del directorio /etc/swift

    # chown -R root:swift /etc/swift

13.5. Iniciar y reiniciar servicios

  1. Reiniciar servicios en nodo de control

    # service memcached restart
    # service swift-proxy restart
  2. Iniciar los servicios de almacenamiento en los nodos de almacenamiento de objetos

    # swift-init all start

14. Sahara

Realizar todos estos pasos en el nodo de control.

  1. Creación y configuración de la base de datos sahara

    MariaDB [(none)]> CREATE DATABASE sahara;
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON sahara.* TO 'sahara'@'localhost' \
      IDENTIFIED BY 'SAHARA_DBPASS'; (1)
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON sahara.* TO 'sahara'@'%' \
      IDENTIFIED BY 'SAHARA_DBPASS'; (2)
    1 Contraseña del usuario Sahara
    2 Contraseña del usuario Sahara
  2. Realizar la configuración de Sahara (usuario sahara, añadir el usuario sahara al proyecto service con el rol admin y crear el servicio sahara)

    # source openrc-admin (1)
    
    # openstack user create --domain default sahara --password {{ sahara_dbpass }} (2)
    # openstack role add --project service --user sahara admin
    # openstack service create --name sahara --description "OpenStack Data Processing" data-processing
    1 Cargar las credenciales de admin
    2 Contraseña del usuario sahara
  3. Crear los endpoints de la API

    # openstack endpoint create --region {{region}} data-processing public http://{{ nodes_by_name.controller.provider_ip }}:8386/v1.1/%\(project_id\)s (1)
    # openstack endpoint create --region {{region}} data-processing internal http://{{ nodes_by_name.controller.tunnel_ip }}:8386/v1.1/%\(project_id\)s (2)
    # openstack endpoint create --region {{region}} data-processing admin http://{{ nodes_by_name.controller.management_ip }}:8386/v1.1/%\(project_id\)s (3)
    1 Región (p.e, RegionOne) e IP externa del nodo de control
    2 Región (p.e, RegionOne) e IP de túnel del nodo de control
    3 Región (p.e, RegionOne) e IP de mantenimiento del nodo de control
  4. Instalar los paquetes de Glance

    # apt install sahara python-saharaclient
  5. Configurar el archivo /etc/sahara/sahara.conf

    El archivo /etc/sahara/sahara.conf
    [DEFAULT]
    
    transport_url = rabbit://openstack:{{ RABBIT_PASS }}@{{ nodes.controller.name }} (1)
    
    use_floating_ips = true
    
    use_neutron = true
    
    heat_enable_wait_condition = false
    
    [castellan]
    
    [cinder]
    
    [conductor]
    
    [cors]
    
    [cors.subdomain]
    
    [database]
    
    connection = mysql://sahara:{{ sahara_dbpass }}@{{ nodes.controller.name }}/sahara (2)
    
    [heat]
    
    [keystone]
    
    [keystone_authtoken]
    
    auth_uri = http://{{ nodes.controller.name }}:5000/v3/ (3)
    
    memcached_servers = {{ nodes.controller.name }}:11211 (4)
    
    identity_uri = http://{{ nodes.controller.name }}:35357/ (5)
    
    admin_user = sahara
    
    admin_password = {{ sahara_dbpass }} (6)
    
    admin_tenant_name = service
    
    [matchmaker_redis]
    
    [neutron]
    
    [nova]
    
    [object_store_access]
    
    [oslo_concurrency]
    
    lock_path = /var/lock/sahara
    
    [oslo_messaging_amqp]
    
    [oslo_messaging_kafka]
    
    [oslo_messaging_notifications]
    
    [oslo_messaging_rabbit]
    
    [oslo_messaging_zmq]
    
    [oslo_policy]
    
    [retries]
    
    [ssl]
    
    [swift]
    
    [timeouts]
    1 Contraseña de RabbitMQ y nombre del nodo de control
    2 Contraseña de Sahara y nombre del nodo de control
    3 Nombre del nodo de control
    4 Nombre del nodo de control
    5 Nombre del nodo de control
    6 Contraseña de Sahara
  6. Añadir lo siguiente a /etc/mysql/my.cnf

    [mysqld]
    max_allowed_packet = 256M
  7. Reiniciar MySQL

    # service mysql restart
  8. Inicializar la base de datos sahara

    # su -s /bin/sh -c "sahara-db-manage --config-file /etc/sahara/sahara.conf upgrade head" sahara
  9. Modificar el archivo /usr/lib/python2.7/dist-packages/sahara/service/quotas.py

    El archivo /usr/lib/python2.7/dist-packages/sahara/service/quotas.py
    from oslo_config import cfg
    import six
    
    from sahara import context
    from sahara import exceptions as ex
    from sahara.i18n import _
    from sahara.utils.openstack import base as b
    from sahara.utils.openstack import cinder as cinder_client
    from sahara.utils.openstack import neutron as neutron_client
    from sahara.utils.openstack import nova as nova_client
    
    CONF = cfg.CONF
    
    UNLIMITED = 'unlimited'
    
    def _is_unlimited(limit):
        return limit == -1
    
    def _get_zero_limits():
        return {
            'ram': 0,
            'cpu': 0,
            'instances': 0,
            'floatingips': 0,
            'security_groups': 0,
            'security_group_rules': 0,
            'ports': 0,
            'volumes': 0,
            'volume_gbs': 0
        }
    
    def check_cluster(cluster):
        req_limits = _get_req_cluster_limits(cluster)
        _check_limits(req_limits)
    
    def check_scaling(cluster, to_be_enlarged, additional):
        req_limits = _get_req_scaling_limits(cluster, to_be_enlarged, additional)
        _check_limits(req_limits)
    
    def _check_limits(req_limits):
        limits_name_map = {
            'ram': _("RAM"),
            'cpu': _("VCPU"),
            'instances': _("instance"),
            'floatingips': _("floating ip"),
            'security_groups': _("security group"),
            'security_group_rules': _("security group rule"),
            'ports': _("port"),
            'volumes': _("volume"),
            'volume_gbs': _("volume storage")
        }
    
        avail_limits = _get_avail_limits()
        for quota, quota_name in six.iteritems(limits_name_map):
            if avail_limits[quota] != UNLIMITED:
                if avail_limits[quota] < req_limits[quota]:
                    raise ex.QuotaException(quota_name, req_limits[quota],
                                            avail_limits[quota])
    
    def _get_req_cluster_limits(cluster):
        req_limits = _get_zero_limits()
        for ng in cluster.node_groups:
            _update_limits_for_ng(req_limits, ng, ng.count)
        return req_limits
    
    def _get_req_scaling_limits(cluster, to_be_enlarged, additional):
        ng_id_map = to_be_enlarged.copy()
        ng_id_map.update(additional)
        req_limits = _get_zero_limits()
        for ng in cluster.node_groups:
            if ng_id_map.get(ng.id):
                _update_limits_for_ng(req_limits, ng, ng_id_map[ng.id] - ng.count)
        return req_limits
    
    def _update_limits_for_ng(limits, ng, count):
        sign = lambda x: (1, -1)[x < 0]
        nova = nova_client.client()
        limits['instances'] += count
        flavor = b.execute_with_retries(nova.flavors.get, ng.flavor_id)
        limits['ram'] += flavor.ram * count
        limits['cpu'] += flavor.vcpus * count
        # tmckay-fp this is fine, it will be zero without it
        if ng.floating_ip_pool:
            limits['floatingips'] += count
        if ng.volumes_per_node:
            limits['volumes'] += ng.volumes_per_node * count
            limits['volume_gbs'] += ng.volumes_per_node * ng.volumes_size * count
        if ng.auto_security_group:
            limits['security_groups'] += sign(count)
            # NOTE: +3 - all traffic for private network
            if CONF.use_neutron:
                limits['security_group_rules'] += (
                    (len(ng.open_ports) + 3) * sign(count))
            else:
                limits['security_group_rules'] = max(
                    limits['security_group_rules'], len(ng.open_ports) + 3)
        if CONF.use_neutron:
            limits['ports'] += count
    
    def _get_avail_limits():
        limits = _get_zero_limits()
        limits.update(_get_nova_limits())
        limits.update(_get_neutron_limits())
        if cinder_client.check_cinder_exists():
            limits.update(_get_cinder_limits())
        return limits
    
    def _sub_limit(total, used):
        if _is_unlimited(total):
            return UNLIMITED
        else:
            return total - used
    
    def _get_nova_limits():
        limits = {}
        nova = nova_client.client()
        lim = b.execute_with_retries(nova.limits.get).to_dict()['absolute']
        limits['ram'] = _sub_limit(lim['maxTotalRAMSize'], lim['totalRAMUsed'])
        limits['cpu'] = _sub_limit(lim['maxTotalCores'], lim['totalCoresUsed'])
        limits['instances'] = _sub_limit(lim['maxTotalInstances'],
                                         lim['totalInstancesUsed'])
        if CONF.use_neutron:
            return limits
    
        # tmckay-fp here we would just get the limits all the time
        limits['floatingips'] = _sub_limit(lim['maxTotalFloatingIps'],
                                           lim['totalFloatingIpsUsed'])
        # limits['floatingips'] = 0
    
        limits['security_groups'] = _sub_limit(lim['maxSecurityGroups'],
                                               lim['totalSecurityGroupsUsed'])
        limits['security_group_rules'] = _sub_limit(lim['maxSecurityGroupRules'],
                                                    0)
        return limits
    
    def _get_neutron_limits():
        limits = {}
        if not CONF.use_neutron:
            return limits
        neutron = neutron_client.client()
        tenant_id = context.ctx().tenant_id
        total_lim = b.execute_with_retries(neutron.show_quota, tenant_id)['quota']
    
        # tmckay-fp here we would just get the limits all the time
        usage_fip = b.execute_with_retries(
           neutron.list_floatingips,  tenant_id=tenant_id)['floatingips']
        limits['floatingips'] = _sub_limit(total_lim['floatingip'],
                                          len(usage_fip))
        # limits['floatingips'] = 0
    
        usage_sg = b.execute_with_retries(
            neutron.list_security_groups, tenant_id=tenant_id).get(
            'security_groups', [])
        limits['security_groups'] = _sub_limit(total_lim['security_group'],
                                               len(usage_sg))
    
        usage_sg_rules = b.execute_with_retries(
            neutron.list_security_group_rules, tenant_id=tenant_id).get(
            'security_group_rules', [])
        limits['security_group_rules'] = _sub_limit(
            total_lim['security_group_rule'], len(usage_sg_rules))
    
        usage_ports = b.execute_with_retries(
            neutron.list_ports, tenant_id=tenant_id)['ports']
        limits['ports'] = _sub_limit(total_lim['port'], len(usage_ports))
    
        return limits
    
    def _get_cinder_limits():
        avail_limits = {}
        cinder = cinder_client.client()
        lim = {}
        for l in b.execute_with_retries(cinder.limits.get).absolute:
            lim[l.name] = l.value
    
        avail_limits['volumes'] = _sub_limit(lim['maxTotalVolumes'],
                                             lim['totalVolumesUsed'])
    
        avail_limits['volume_gbs'] = _sub_limit(lim['maxTotalVolumeGigabytes'],
                                                lim['totalGigabytesUsed'])
    
        return avail_limits
  10. Reiniciar los servicios de Sahara

    # service sahara-api restart
    # service sahara-engine restart
  11. Clonar el repositorio de sahara-dashboard

    # git clone https://github.com/openstack/sahara-dashboard /tmp/sahara-dashboard

    Sahara no tiene empaquetada la integración con Horizon. En estos casos descargaremos los fuentes del dashboard, los procesaremos y los integraremos en Horizon.

  12. Instalar el dashboard de Sahara desde /tmp/sahara-dashboard/

    # cd /tmp/sahara-dashboard/
    # python setup.py install
  13. Copiar los archivos del dashboard de Sahara

    # cp /tmp/sahara-dashboard/sahara_dashboard/enabled/_1810_data_processing_panel_group.py /usr/share/openstack-dashboard/openstack_dashboard/enabled/
    # cp /tmp/sahara-dashboard/sahara_dashboard/enabled/_1830_data_processing_plugins_panel.py /usr/share/openstack-dashboard/openstack_dashboard/enabled/
    # cp /tmp/sahara-dashboard/sahara_dashboard/enabled/_1820_data_processing_clusters_panel.py /usr/share/openstack-dashboard/openstack_dashboard/enabled/
    # cp /tmp/sahara-dashboard/sahara_dashboard/enabled/_1840_data_processing_jobs_panel.py /usr/share/openstack-dashboard/openstack_dashboard/enabled/
  14. Realizar estos últimos pasos para terminar de integrar el dashboard en Horizon

    # cd /usr/share/openstack-dashboard
    # python manage.py collectstatic (1)
    # python manage.py compress
    1 Responder yes a la pregunta
  15. Reiniciar el servidor Apache

    # service apache2 restart

Anexo 1. Esquema de red

Conexiones.png

Anexo 2. Paquetes y archivos de configuración

La instalación de OpenStack es un proceso farragoso en cuanto a la cantidad de paquetes y archivos de configuración que hay que instalar y configuirar en cada tipo de nodo. A continuación se muestran dos figuras que ilustran los paquetes a instalar y los archivos a configurar en cada nodo.

OpenStackPackagesAndFilesController.png
Figure 3. Paquetes y archivos a configurar en el nodo de control
OpenStackPackagesAndFilesRemainder.png
Figure 4. Paquetes y archivos a configurar en el resto de nodos

Anexo 3. Servicios en ejecución en cada servidor

Servicios en el nodo de control

  • chrony

  • mysql

  • rabbitmq

  • memcached

  • apache2

  • glance-api: Discovery, recuperación y almacenamiento de imágenes.

  • glance-registry: Creación, modificación y consulta de metadatos de las imágenes (p.e. tamaño, tipo)

  • nova-api

  • nova-placement-api: Inventario y uso de cada provider.

  • nova-scheduler: Gestiona peticiones de máquinas virtuales a los nodos de cómputo.

  • nova-consoleauth: Da tokens de acceso a los usuarios

  • nova-novncproxy: Acceso VNC a las instancias (clientes VNC basados en navegadores compatibles).

  • neutron-server: Acepta y emite peticiones a la API del plugin correspondiente (bridging/switching, DHCP, …​)

  • ml2-agent: Bridging/switching

  • cinder-api

  • cinder-scheduler: Gestiona peticiones de almacenamiento de bloques.

  • manila-api

  • manila-scheduler: Gestiona peticiones de almacenamiento de archivos

  • swift-proxy

  • heat-api

  • heat-engine

  • heat-api-ctn

  • barbican-keystone-listener

  • barbican-worker

  • sabana-api

  • sabana-engine

Servicios en el nodo de red

  • chrony

  • openvswitch-agent: Bridging/switching para redes virtuales.

  • dhcp-agent: Servicios de DHCP para redes virrtuales.

  • `metadata-agent`Servicios de metadatos a las instancias.

  • l3-agent

Servicios en nodos de cómputo

  • chrony

  • nova-compute: Crea y termina máquinas virtuales a través de la API del hipervisor

  • openvswitch-agent: Bridging/switching para redes virtuales.

Servicios en el nodo de almacenamiento de bloques

  • chrony

  • cinder-volume

  • lvm2

  • tgt

Servicios en el nodo de almacenamiento de archivos compartidos

  • chrony

  • manila-share

  • lvm2

Servicios en el nodo de almacenamiento de objetos

  • chrony

  • swift-account

  • swift-account-auditor

  • swift-account-reaper

  • swift-account-replicator

  • swift-container

  • swift-container-auditor

  • swift-container-replicator

  • swift-container-sync

  • swift-container-updater

  • swift-object

  • swift-object-auditor

  • swift-object-reconstructor

  • swift-object-replicator

  • swift-object-updater

Anexo 4. Tablas no vacías de las bases de datos de OpenStack

+--------------------+----------------------------------------------------+
| table_schema       | table_name                                         |
+--------------------+----------------------------------------------------+
| barbican           | alembic_version                                    |
| barbican           | certificate_authorities                            |
| barbican           | certificate_authority_metadata                     |
| barbican           | container_secret                                   |
| barbican           | containers                                         |
| barbican           | encrypted_data                                     |
| barbican           | secret_store_metadata                              |
| barbican           | secrets                                            |
| cinder             | messages                                           |
| cinder             | quota_classes                                      |
| cinder             | quota_usages                                       |
| cinder             | quotas                                             |
| cinder             | reservations                                       |
| cinder             | services                                           |
| cinder             | snapshot_metadata                                  |
| cinder             | snapshots                                          |
| cinder             | transfers                                          |
| cinder             | volume_admin_metadata                              |
| cinder             | volume_attachment                                  |
| cinder             | volume_glance_metadata                             |
| cinder             | volume_metadata                                    |
| cinder             | volumes                                            |
| cinder             | workers                                            |
| glance             | alembic_version                                    |
| glance             | image_locations                                    |
| glance             | image_properties                                   |
| glance             | images                                             |
| heat               | event                                              |
| heat               | raw_template                                       |
| heat               | raw_template_files                                 |
| heat               | resource                                           |
| heat               | resource_data                                      |
| heat               | resource_properties_data                           |
| heat               | service                                            |
| heat               | software_config                                    |
| heat               | stack                                              |
| heat               | user_creds                                         |
| keystone           | assignment                                         |
| keystone           | credential                                         |
| keystone           | endpoint                                           |
| keystone           | local_user                                         |
| keystone           | migrate_version                                    |
| keystone           | password                                           |
| keystone           | project                                            |
| keystone           | revocation_event                                   |
| keystone           | role                                               |
| keystone           | service                                            |
| keystone           | trust                                              |
| keystone           | trust_role                                         |
| keystone           | user                                               |
| manila             | alembic_version                                    |
| manila             | quota_usages                                       |
| manila             | quotas                                             |
| manila             | reservations                                       |
| manila             | services                                           |
| manila             | share_instance_export_locations                    |
| manila             | share_instance_export_locations_metadata           |
| manila             | share_instances                                    |
| manila             | shares                                             |
| neutron            | agents                                             |
| neutron            | alembic_version                                    |
| neutron            | alembic_version_fwaas                              |
| neutron            | alembic_version_lbaas                              |
| neutron            | default_security_group                             |
| neutron            | dnsnameservers                                     |
| neutron            | floatingips                                        |
| neutron            | ipallocationpools                                  |
| neutron            | ipallocations                                      |
| neutron            | ipamallocationpools                                |
| neutron            | ipamallocations                                    |
| neutron            | ipamsubnets                                        |
| neutron            | lbaas_healthmonitors                               |
| neutron            | lbaas_listeners                                    |
| neutron            | lbaas_loadbalancer_statistics                      |
| neutron            | lbaas_loadbalanceragentbindings                    |
| neutron            | lbaas_loadbalancers                                |
| neutron            | lbaas_members                                      |
| neutron            | lbaas_pools                                        |
| neutron            | ml2_port_binding_levels                            |
| neutron            | ml2_port_bindings                                  |
| neutron            | ml2_vxlan_allocations                              |
| neutron            | ml2_vxlan_endpoints                                |
| neutron            | networkdhcpagentbindings                           |
| neutron            | networkrbacs                                       |
| neutron            | networks                                           |
| neutron            | networksecuritybindings                            |
| neutron            | networksegments                                    |
| neutron            | ports                                              |
| neutron            | portsecuritybindings                               |
| neutron            | providerresourceassociations                       |
| neutron            | provisioningblocks                                 |
| neutron            | quotas                                             |
| neutron            | quotausages                                        |
| neutron            | router_extra_attributes                            |
| neutron            | routerl3agentbindings                              |
| neutron            | routerports                                        |
| neutron            | routers                                            |
| neutron            | securitygroupportbindings                          |
| neutron            | securitygrouprules                                 |
| neutron            | securitygroups                                     |
| neutron            | standardattributes                                 |
| neutron            | subnets                                            |
| nova               | block_device_mapping                               |
| nova               | compute_nodes                                      |
| nova               | instance_actions                                   |
| nova               | instance_actions_events                            |
| nova               | instance_extra                                     |
| nova               | instance_faults                                    |
| nova               | instance_id_mappings                               |
| nova               | instance_info_caches                               |
| nova               | instance_metadata                                  |
| nova               | instance_system_metadata                           |
| nova               | instances                                          |
| nova               | migrations                                         |
| nova               | quota_usages                                       |
| nova               | quotas                                             |
| nova               | reservations                                       |
| nova               | s3_images                                          |
| nova               | security_groups                                    |
| nova               | services                                           |
| nova               | task_log                                           |
| nova               | virtual_interfaces                                 |
| nova_api           | allocations                                        |
| nova_api           | cell_mappings                                      |
| nova_api           | flavor_projects                                    |
| nova_api           | flavors                                            |
| nova_api           | host_mappings                                      |
| nova_api           | instance_group_member                              |
| nova_api           | instance_group_policy                              |
| nova_api           | instance_groups                                    |
| nova_api           | instance_mappings                                  |
| nova_api           | inventories                                        |
| nova_api           | key_pairs                                          |
| nova_api           | request_specs                                      |
| nova_api           | resource_providers                                 |
| nova_cell0         | instance_extra                                     |
| nova_cell0         | instance_faults                                    |
| nova_cell0         | instance_id_mappings                               |
| nova_cell0         | instance_info_caches                               |
| nova_cell0         | instance_system_metadata                           |
| nova_cell0         | instances                                          |
| nova_cell0         | quota_usages                                       |
| nova_cell0         | s3_images                                          |
| nova_cell0         | security_groups                                    |
| sahara             | alembic_version                                    |
+--------------------+----------------------------------------------------+

Anexo 5. Consultas SQL de utilidad

  1. Ids de proyectos

    = SELECT id
    FROM keystone.project
    WHERE name IN ('proyecto1', 'proyecto2'); (1)
    1 Pasar los nombre de proyecto como parámetro
  2. Imágenes de cada proyecto

    SELECT I.id, I.name, P.name
    FROM glance.images I JOIN keystone.project P ON I.owner = P.id;
  3. Imágenes de proyectos concretos

    SELECT I.id, I.name, P.name
    FROM glance.images I JOIN keystone.project P ON I.owner = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy')
    ) ORDER BY I.id;
  4. Eliminar imágenes de proyectos concretos

    SELECT CONCAT ('openstack image delete ', I.id)
    FROM glance.images I JOIN keystone.project P ON I.owner = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy')
    ) ORDER BY I.id;
  5. Instances de proyectos concretos

    SELECT I.uuid, I.hostname, P.name
    FROM nova.instances I JOIN keystone.project P ON I.project_id = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy')
    ) ORDER BY I.uuid
    ;
  6. Eliminar instancias de proyectos concretos

    SELECT CONCAT ('openstack delete server ', I.uuid)
    FROM nova.instances I JOIN keystone.project P ON I.project_id = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy')
    ) ORDER BY I.uuid
    ;
  7. Attachements de volúmenes de instancias proyectos concretos

    SELECT A.instance_uuid, A.id, A.mountpoint, I.hostname
    FROM cinder.volume_attachment A JOIN nova.instances I ON A.instance_uuid = I.uuid
    WHERE A.instance_uuid IN (
    SELECT I.uuid
    FROM nova.instances I JOIN keystone.project P ON I.project_id = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy'))
    ) ORDER BY A.instance_uuid, A.id;
  8. Dettach los volúmenes de las instancias de proyectos concretos

    SELECT CONCAT ('openstack server remove volume ', A.instance_uuid, ' ', A.id)
    FROM cinder.volume_attachment A JOIN nova.instances I ON A.instance_uuid = I.uuid
    WHERE A.instance_uuid IN (
    SELECT I.uuid
    FROM nova.instances I JOIN keystone.project P ON I.project_id = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy'))
    ) ORDER BY A.instance_uuid, A.id;
  9. Volúmenes de proyetos concretos

    SELECT V.id, V.host, V.size, V.display_name
    FROM cinder.volumes V JOIN keystone.project P ON V.project_id = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy')
    ) ORDER BY V.id;
  10. Eliminar volúmenes de proyectos concretos

    SELECT CONCAT ('openstack volume delete ', V.id)
    FROM cinder.volumes V JOIN keystone.project P ON V.project_id = P.id
    WHERE P.id IN (
    SELECT id
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy')
    ) ORDER BY V.id;
  11. Proyectos concretos

    SELECT id, name
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy');
  12. Eliminar proyectos concretos

    SELECT CONCAT ('openstack project delete ' , id)
    FROM keystone.project
    WHERE name IN ('xxxx', 'yyyy');