# OpenStack Train
## Component Dependency
The following diagram conforms to [this](https://www.openstack.org/software/project-navigator/openstack-components#openstack-services).
```graphviz
digraph hierarchy {
#nodesep=1.0
node [color=Red,fontname="Sans Serif"]
edge [color=Blue,style=dashed]
sql -> {keystone glance}
keystone -> {glance neutron horizon cinder heat karbor }
{keystone glance neutron} -> nova
placement
{keystone nova cinder neutron glance swift} -> ironic
{keystone nova cinder glance swift} -> trove
}
```
According to [this](https://docs.openstack.org/install-guide/openstack-services.html#minimal-deployment-for-train),
the minimal components that make up a functional openstack node includes:
- keystone, glance, placement, nova, neutron
Additional recommended installs includes:
- horizon, cinder
The components we wish to use are:
- ironic, heat, karbor, trove
## CentOS 7
Run everything in `screen`.
The `vt102` emulation of `screen` is so much better.
```
virt-install \
--name $1 \
--memory 8192 \
--vcpus 4 \
--os-variant centos7.0 \
--disk pool=cloud_storage,size=60,sparse=false,cache=none,io=native,bus=virtio \
--disk vol=default/CentOS-7-x86_64-NetInstall-2003.iso,device=cdrom \
--boot hd,cdrom,useserial=on,menu=on \
--network network=default,model=virtio \
--graphics none \
--noautoconsole \
--noreboot
```
1. Press `TAB` on boot menu, and enter `console=ttyS0`.
2. Configure network.
3. NTP: `tw.pool.ntp.org`.
4. Mirror: `http://centos.cs.nctu.edu.tw/7/os/x86_64/`.
5. Use `LVM`.
6. Don't set `root` password.
```
umount /dev/mapper/centos_undercloud-home
lvremove /dev/mapper/centos_undercloud-home
lvresize /dev/mapper/centos_undercloud-root /dev/vda2
xfs_growfs /dev/mapper/centos_undercloud-root
sed -i '/\/home/d' /etc/fstab
```
```
echo "192.168.122.251 controller" >> /etc/hosts
yum install -y vim
yum update
reboot
```
## Preparation
### NTP
```
yum install -y chrony
```
In `/etc/chrony.conf`:
```
server tw.pool.ntp.org iburst
allow 10.0.0.11/24
```
Systemd.
```
systemctl enable chronyd
systemctl start chronyd
```
Verify.
```
chronyc sources
```
### OpenStack packages
We will be using the RDO repo.
It is suggested to disable the EPEL repo.
Enable the OpenStack repository.
```
yum install -y centos-release-openstack-train
yum upgrade -y
yum install -y python-openstackclient
yum install -y openstack-selinux
```
### SQL database
:::warning
Quote from [here](https://docs.openstack.org/install-guide/environment-sql-database.html).
If you see Too many connections or Too many open files error log messages on OpenStack services, verify that maximum number of connection settings are well applied to your environment. In MariaDB, you may also need to change [open_files_limit](https://mariadb.com/kb/en/library/server-system-variables/#open_files_limit) configuration.
:::
```
yum install -y mariadb mariadb-server python2-PyMySQL
```
Create the `/etc/my.cnf.d/openstack.cnf` with content:
```
[mysqld]
bind-address = 10.0.0.11
default-storage-engine = innodb
innodb_file_per_table = on
max_connections = 4096
collation-server = utf8_general_ci
character-set-server = utf8
```
systemd
```
systemctl enable mariadb
systemctl start mariadb
```
Set password for database.
```
mysql_secure_installation
```
### Message queue (RABBIT_PASS)
```
yum install -y rabbitmq-server
systemctl enable rabbitmq-server
systemctl start rabbitmq-server
rabbitmqctl add_user openstack RABBIT_PASS
rabbitmqctl set_permissions openstack ".*" ".*" ".*"
```
### Memcached
```
yum install -y memcached python-memcached
sed -i '/127.0.0.1/c\OPTIONS="-l 127.0.0.1,::1,controller"' /etc/sysconfig/memcached
systemctl enable memcached
systemctl start memcached
```
### Etcd
```
yum install -y etcd
sed -i "s/localhost/192.168.122.251/g" /etc/etcd/etcd.conf
sed -i 's/ETCD_NAME/ETCD_NAME="controller"/' /etc/etcd/etcd.conf
for str in \
ETCD_DATA_DIR \
ETCD_LISTEN_PEER_URLS \
ETCD_LISTEN_CLIENT_URLS \
ETCD_NAME \
ETCD_INITIAL_ADVERTISE_PEER_URLS \
ETCD_ADVERTISE_CLIENT_URLS \
ETCD_INITIAL_CLUSTER \
ETCD_INITIAL_CLUSTER_TOKEN \
ETCD_INITIAL_CLUSTER_STATE
do sed -i "/${str}/s/^#//" /etc/etcd/etcd.conf ; done
systemctl enable etcd
systemctl start etcd
```
## Keystone (KEYSTONE_DBPASS, ADMIN_PASS)
```
mysql -u root -p
MariaDB [(none)]> CREATE DATABASE keystone;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'KEYSTONE_DBPASS';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'KEYSTONE_DBPASS';
MariaDB [(none)]> exit
```
```
yum install -y openstack-keystone httpd mod_wsgi
for str in connection provider
do sed -i "/${str}/s/^#//" /etc/keystone/keystone.conf ; done
sed -i "/^connection/c\connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone" /etc/keystone/keystone.conf
```
```
[database]
# ...
connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone
[token]
# ...
provider = fernet
```
```
# Slow
su -s /bin/sh -c "keystone-manage db_sync" keystone
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
keystone-manage credential_setup --keystone-user keystone --keystone-group keystone
keystone-manage bootstrap --bootstrap-password ADMIN_PASS \
--bootstrap-admin-url http://controller:5000/v3/ \
--bootstrap-internal-url http://controller:5000/v3/ \
--bootstrap-public-url http://controller:5000/v3/ \
--bootstrap-region-id RegionOne
```
```
echo "ServerName controller" >> /etc/httpd/conf/httpd.conf
ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/
systemctl enable httpd
systemctl start httpd
```
Create `keystonerc` with content.
```
export OS_USERNAME=admin
export OS_PASSWORD=ADMIN_PASS
export OS_PROJECT_NAME=admin
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
```
Source `keystonerc`.
```
openstack domain create --description "An Example Domain" example
openstack project create --domain default --description "Service Project" service
openstack project create --domain default --description "Demo Project" myproject
openstack user create --domain default --password-prompt myuser
openstack role create myrole
openstack role add --project myproject --user myuser myrole
```
```
unset OS_AUTH_URL OS_PASSWORD
openstack \
--os-auth-url http://controller:5000/v3 \
--os-project-domain-name Default \
--os-user-domain-name Default \
--os-project-name admin \
--os-username admin token issue
openstack \
--os-auth-url http://controller:5000/v3 \
--os-project-domain-name Default \
--os-user-domain-name Default \
--os-project-name myproject \
--os-username myuser token issue
```
Create `admin-openrc` with content:
```
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=ADMIN_PASS
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
```
Create `demo-openrc` with content:
```
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=myproject
export OS_USERNAME=myuser
export OS_PASSWORD=DEMO_PASS
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
```
To test them, source `admin-openrc`, and run:
```
openstack token issue
```
## Glance (GLANCE_DBPASS)
```
mysql -u root -p
MariaDB [(none)]> CREATE DATABASE glance;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY 'GLANCE_DBPASS';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY 'GLANCE_DBPASS';
MariaDB [(none)]> exit
```
Source `admin-openrc`, and create user/service associated with glance.
```
openstack user create --domain default --password-prompt glance
openstack role add --project service --user glance admin
openstack service create --name glance --description "OpenStack Image" image
openstack endpoint create --region RegionOne image public http://controller:9292
openstack endpoint create --region RegionOne image internal http://controller:9292
openstack endpoint create --region RegionOne image admin http://controller:9292
```
```
yum install -y openstack-glance
```
Edit `/etc/glance/glance-api.conf`.
```
[database]
# ...
connection = mysql+pymysql://glance:GLANCE_DBPASS@controller/glance
[keystone_authtoken]
# ...
www_authenticate_uri = http://controller:5000
auth_uri = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = glance
password = GLANCE_PASS
[paste_deploy]
# ...
flavor = keystone
[glance_store]
# ...
stores = file,http
default_store = file
filesystem_store_datadir = /var/lib/glance/images/
```
```
su -s /bin/sh -c "glance-manage db_sync" glance
systemctl enable openstack-glance-api
systemctl start openstack-glance-api
```
## Placement
### [Verification](https://docs.openstack.org/placement/ussuri/install/verify.html)
Source `admin-openrc`, and run:
```
placement-status upgrade check
```
It shoud print something like this:
```
+----------------------------------+
| Upgrade Check Results |
+----------------------------------+
| Check: Missing Root Provider IDs |
| Result: Success |
| Details: None |
+----------------------------------+
| Check: Incomplete Consumers |
| Result: Success |
| Details: None |
+----------------------------------+
```
Install the `osc-placement` plugin.
The official document installs the plugin with `pip`.
It is possible, and probably recommended, to install it from the OpenStack repo.
```
dnf install -y python3-osc-placement
```
Then, the document instructs on running the commands:
```
openstack --os-placement-api-version 1.2 resource class list --sort-column name
openstack --os-placement-api-version 1.6 trait list --sort-column name
```
They should print something like:
```
+----------------------------+
| name |
+----------------------------+
| DISK_GB |
| FPGA |
| IPV4_ADDRESS |
| MEMORY_MB |
| MEM_ENCRYPTION_CONTEXT |
| NET_BW_EGR_KILOBIT_PER_SEC |
| NET_BW_IGR_KILOBIT_PER_SEC |
| ... |
+---------------------------------------+
| name |
+---------------------------------------+
| COMPUTE_ACCELERATORS |
| COMPUTE_DEVICE_TAGGING |
| COMPUTE_GRAPHICS_MODEL_CIRRUS |
| COMPUTE_GRAPHICS_MODEL_GOP |
| COMPUTE_GRAPHICS_MODEL_NONE |
| COMPUTE_GRAPHICS_MODEL_QXL |
| COMPUTE_GRAPHICS_MODEL_VGA |
| ... |
```
In fact, the lists are quite lengthy.
I tried piping the output to `head`.
Sometime the command will voice the complaint:
```
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
```
The message above is no big deal.
However, the following message is huge:
```
Expecting value: line 1 column 1 (char 0)
```
According to [this](https://ask.openstack.org/en/question/122022/stein-expecting-value-line-1-column-1-char-0-oscplacement/),
add the following to `/etc/httpd/conf.d/00-placement-api.conf`:
```
<Directory /usr/bin>
<IfVersion >= 2.4>
Require all granted
</IfVersion>
<IfVersion < 2.4>
Order allow,deny
Allow from all
</IfVersion>
</Directory>
```
Then, restart the *httpd* service.
## clouds.yaml
- [openstack-client](https://docs.openstack.org/python-openstackclient/ussuri/configuration/index.html#configuration-files)
- [keystone plugin](https://docs.openstack.org/keystoneauth/ussuri/plugin-options.html)
---
- [apache frontend](https://docs.openstack.org/swift/latest/apache_deployment_guide.html)
- [nginx frontend](https://specs.openstack.org/openstack/openstack-ansible-specs/specs/rocky/centralized-nginx.html)
- [wsgi considerations for nova](https://docs.openstack.org/nova/ussuri/user/wsgi.html)
---
- [keystone DOS](https://wiki.openstack.org/wiki/OSSN/1155566)
- [token revocation DOS](https://wiki.openstack.org/wiki/OSSN/OSSN-0068)
---
- [ldap.org on chosing LDAP](https://ldap.com/why-choose-ldap/)
- [more on LDAP vs SQL](https://stackoverflow.com/questions/5075394/difference-between-sql-and-ldap)
- [OpenStack wiki on LDAP](https://wiki.openstack.org/wiki/OpenLDAP)
- [keystone with LDAP](https://docs.openstack.org/keystone/ussuri/admin/configuration.html#integrate-identity-with-ldap)
---
- [keystone X.509](https://docs.openstack.org/keystone/ussuri/admin/configure_tokenless_x509.html)
- [openstack tls security](https://docs.openstack.org/security-guide/secure-communication.html)