setting kolla-ansible rocky environment and a simple python-openstackclient code test

# SERVER SIDE / OPENSTACK

cloud.z.com에서 메모리 16기가의 가상머신을 준비했다.
on cloud.z.com, I prepared a virtual machine with 16GB RAM 50G disk.

네트웍은 글로벌 넷트웍하나, 프라이빗네트웍 하나를 준비했다. 글로벌이 eth0, 프라이빗이 eth1로 제공된다.
The network interfaces are two. one for global network and one for private network. the global is provided as eth0 and the private as eth1.


![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/aa0391f3-ba42-4191-9778-fc76ec9760ba.png)

kolla-ansible을 사용해서 가상머신에 openstack 컴포넌트들을 설치했다. 순서는 다음의 qiita를 참고했는데, 
I used kolla-ansible to install the openstack components on my virtual machine. I referred following qiita post;

[kolla-ansibleでOpenStack(stable/queens)を構築する](https://qiita.com/raichi/items/3efeae6685f7451f6257#2-%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E5%89%8D%E6%BA%96%E5%82%99)

여러번 반복해서 하다보니 ansible로 만들었다. 처음에 ``yum install python-pip -y && pip install ansible`` 로 시작하면 된다.
as I repeated the installation several times and made it ansible script finally. Start with `` yum install python-pip -y && pip install ansible``.

anible파일을 kolla-rocky.yml로 저장한 다음 ``ansible-playbook kolla-rocky.yml``로 실행한다.
You can save the anible file as kolla-rocky.yml and run it as `` ansible-playbook kolla-rocky.yml``.


```yaml
# yum install python-pip -y
# pip install ansible
---
- hosts: localhost
  vars:
    - hoge: ""

  tasks:
    - name: yum update
      yum: name=* state=latest

    - name: install kolla rockey
      yum: 
        name: ['epel-release', 'python-pip', 'python-devel', 'libffi-devel', 'gcc', 'openssl-devel', 'libselinux-python', 'git', 'byobu', 'ansible']

    - name: edit ansible.cfg
      lineinfile:
        path: /etc/ansible/ansible.cfg
        insertafter: "[defaults]"
        line: "{{ item }}"
      with_items:
        - 'host_key_checking=False'
        - 'pipelining=True'
        - 'forks=100'
        - 'validate_certs=False'

    - name: git clone kolla-ansible
      git:
        repo: 'https://github.com/openstack/kolla-ansible'
        dest: /opt/kolla-ansible
        version: stable/rocky

    - name: install requirements
      pip:
        requirements: /opt/kolla-ansible/requirements.txt
        extra_args: --ignore-installed

    - name: install kolla-ansible
      command: chdir=/opt/kolla-ansible python setup.py install

    - name: copy deploy files
      command: cp -r /opt/kolla-ansible/etc/kolla /etc/kolla/

    - name: copy deploy inventory files
      command: cp -r /opt/kolla-ansible/ansible/inventory/{{item}} /opt
      with_items:
        - 'all-in-one'
        - 'multinode'

    - name: generate password filfiles
      command: /usr/bin/kolla-genpwd

    - name: edit /etc/kolla/globals.yml
      lineinfile:
        path: /etc/kolla/globals.yml
        regexp: "{{ item.regexp }}" # find line
        state: present # replace
        line: "{{ item.line}}"
      with_items:
        - { regexp: "^#?kolla_base_distro:", line: 'kolla_base_distro: "centos"'}
        - { regexp: "^#?kolla_install_type:", line: 'kolla_install_type: "source"'}
        - { regexp: "^#?openstack_release:", line: 'openstack_release: "rocky"'}
        - { regexp: "^#?kolla_internal_vip_address:", line: 'kolla_internal_vip_address: "{{ansible_eth0.ipv4.address}}"'}
        - { regexp: "^#?docker_registry:", line: 'docker_registry: ""'}
        - { regexp: "^#?docker_namespace:", line: 'docker_namespace: "kolla"'}
        - { regexp: "^#?network_interface:", line: 'network_interface: "eth0"'}
        - { regexp: "^#?neutron_external_interface:", line: 'neutron_external_interface: "eth1"'}
        - { regexp: "^#?enable_haproxy:", line: 'enable_haproxy: "no"'}
        - { regexp: "^#?nova_compute_virt_type:", line: 'nova_compute_virt_type: "qemu"'}

    - name: print message
      vars:
        msg: |
             now you can do following;
             cd /opt && kolla-ansible -i all-in-one bootstrap-servers && kolla-ansible -i all-in-one prechecks && kolla-ansible -i all-in-one deploy && kolla-ansible post-deploy && source /etc/kolla/admin-openrc.sh && source /usr/share/kolla-ansible/init-runonce
             or
             kolla-ansible destroy --yes-i-really-really-mean-it
      debug:
        msg: "{{ msg.split('\n') }}"

    - name: install openstack command
      pip:
        name: python-openstackclient,python-glanceclient,python-neutronclient
        state: latest

    - name: print openstack command to create a server
      debug:
        msg: "openstack server create --image cirros --flavor m1.tiny --key-name mykey --network demo-net demo1"
        
```
위의 ansible은 kolla-ansible을 준비하고, 설정을 잡는 것 까지만 한다. 실제로 실행하는 kolla-ansible을 구동하는 코드는 다음과 같다.

The above is for preparation of kolla-ansible environment and configuration. Here is the code to run kolla-ansible which actually executes:

``cd /opt && kolla-ansible -i all-in-one bootstrap-servers && kolla-ansible -i all-in-one prechecks && kolla-ansible -i all-in-one deploy && kolla-ansible post-deploy && source /etc/kolla/admin-openrc.sh && source /usr/share/kolla-ansible/init-runonce``


![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/557e0cd4-d80c-a370-01f4-90cec2306e94.png)


# OPENSTACK CLIENT SIDE

이쪽은 가상머신으로 윈도우즈를 선택했고, IDE는 pycharm을 설치했다.
I set a Windows virtual machine, and Pycharm IDE.

우선 conda 로 설치할 수 있는 것은 먼저 설치하고, 그렇지 못한 것들은 pip로 라이브러리를 설치했다.
I worked on the things I can install with conda first, and I installed the others with pip.

## python code
```python
"""Simple Python script for querying the status of P3 instances.

This script assumes that the following Python 2 packages are installed.

    python-openstackclient>=3.12.0

This can be done with the following commands

    virtualenv alaska-venv
    source alaska-venv/bin/activate
    pip install -U pip setuptools
    pip install python-openstackclient

This script assumes that the openstack RC file v3 (downloaded from the
OpenStack Hoirizon dashboard) has been sourced, eg.

    source p3-openrc.sh

"""
from __future__ import print_function
import sys
import os
import time
import datetime
import logging
from collections import defaultdict
from keystoneauth1.identity import v3
from keystoneauth1 import session
from keystoneclient.v3 import client as keystone_client
from novaclient import client as nova_client


def get_session():
    """Return keystone session"""

    # Extract environment variables set when sourcing the openstack RC file.
    user_domain = os.environ.get('OS_USER_DOMAIN_NAME')
    user = os.environ.get('OS_USERNAME')
    password = os.environ.get('OS_PASSWORD')
    project_id = os.environ.get('OS_PROJECT_ID')
    auth_url = os.environ.get('OS_AUTH_URL')

    # Create user / password based authentication method.
    # https://goo.gl/VxD2FQ
    auth = v3.Password(user_domain_name=user_domain,
                       username=user,
                       password=password,
                       project_id=project_id,
                       auth_url=auth_url)

    # Create OpenStack keystoneauth1 session.
    # https://goo.gl/BE7YMt
    sess = session.Session(auth=auth)

    return sess


def get_user_map(keystone_session):
    """Get map of users from keystone"""
    # FIXME(BM) It would be good to get a map of user names - user id
    # from keystone but this doenst seem to work...
    keystone = keystone_client.Client(session=keystone_session)
    print(type(keystone))
    projects = keystone.projects.list()
    print(projects)
    users = keystone.users.list()
    print(users)


def get_flavor_map(nova_client):
    """Get a map of flavours"""
    log = logging.getLogger(__name__)
    flavors = defaultdict()

    log.info('Flavours (index | id (short) | name):')
    log.info('-' * 80)
    for idx, flavor in enumerate(nova_client.flavors.list()):
        log.info('%03i | %.8s | %s', idx, flavor.id, flavor.human_id)
        flavors[flavor.id] = flavor.human_id
    log.info('-' * 80)
    log.info('')

    return flavors


def query_servers(nova_client):
    """Query list of servers.

    Returns a dictionary of server dictionaries with the key being the
    server name
    """
    log = logging.getLogger(__name__)
    log.info('Servers (index | id (short) | name):')
    log.info('-' * 80)
    servers = defaultdict()
    for idx, server in enumerate(nova_client.servers.list()):
        log.info('%03i | %.8s | %s', idx, server.id, server.human_id)
        server_dict = server.to_dict()
        servers[server.human_id] = server_dict
    log.info('-' * 80)
    log.info('')
    return servers


def server_flavour_summary(servers, flavours):
    """Log a summary of servers by flavor."""
    log = logging.getLogger(__name__)
    log.info('Summary (index | flavour | instance count):')
    log.info('-' * 80)
    for idx, flavor_id in enumerate(flavours):
        count = 0
        for key in servers:
            if servers[key]['flavor']['id'] == flavor_id:
                count += 1
        log.info('%03i | %-20s | %i', idx, flavours[flavor_id], count)
    log.info('-' * 80)
    log.info('')


def user_summary(servers, users):
    """Log a summary of the servers by user."""
    log = logging.getLogger(__name__)
    user_info = defaultdict()
    for idx, key in enumerate(servers):
        user_id = servers[key]['user_id']
        if user_id not in users:
            users[user_id] = 'user-{:02d}'.format(len(users))
        if user_id not in user_info:
            user_info[user_id] = defaultdict(count=0, server_ids=[])
        user_info[user_id]['count'] += 1
        user_info[user_id]['server_ids'].append(key)

    log.info('Users (index | user id (short) | user name | instance count):')
    log.info('-' * 80)
    for idx, key in enumerate(user_info):
        count = user_info[key]['count']
        log.info('%03i | %.8s | %-12s | %-3i',
                 idx, key, users[key], count)
        for server in user_info[key]['server_ids']:
            created = time.strptime(servers[server]['created'],
                                    '%Y-%m-%dT%H:%M:%SZ')
            age = time.mktime(time.localtime()) - time.mktime(created)
            age = datetime.timedelta(seconds=age)
            log.debug('    |-> (age: %3id) %-20s', age.days, server)
    log.info('-' * 80)
    log.info('')


def main():
    """Main function."""
    # Get a keystone session.
    sess = get_session()

    # Create a OpenStack nova client.
    # https://goo.gl/ryuyzF
    nova = nova_client.Client(version=2, session=sess)

    users = defaultdict(str)
    users['1d6abb726dd04d4eb4b894e19c397d0e'] = 'Vlad'
    flavors = get_flavor_map(nova)
    servers = query_servers(nova)
    server_flavour_summary(servers, flavors)
    user_summary(servers, users)


if __name__ == '__main__':
    LOG = logging.getLogger(__name__)
    LOG.setLevel(logging.INFO)
    LOG.addHandler(logging.StreamHandler(sys.stdout))
    main()

```

```
conda install -c conda-forge cryptography PyYAML SQLAlchemy bcrypt paramiko
pip install --ignore-installed osc-lib osc-placement python-openstackclient python-glanceclient python-neutronclient python-novaclient kombu kolla Tempest ceilometer keystone shade
```

## 실행할 때 환경변수를 넘기는 화면
a screen passing environment variables when running the test
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/1e1378fc-3d39-6df9-4aee-51815fd01ba4.png)

## 실행결과
and the result
![image.png](https://qiita-image-store.s3.amazonaws.com/0/12587/e43ac8e8-7520-be40-2842-19c28f0e5bf3.png)