3

目录

【任务 3】私有云运维开发10 分

【题目 1】Ansible 服务部署:部署 MariaDB 集群2 分

【题目 2】Ansible 服务部署:部署ELK 集群服务2 分

【题目 3】Python 运维开发:基于OpenStack Restful API 实现镜像上传1 分

【题目 4】Python 运维开发:基于 Openstack Python SDK 实现云主机创建1 分

【题目 5】Python 运维开发:云主机类型管理的命令行工具开发2 分

【题目 6】Python 运维开发:用户管理的命令行工具开发2 分

【任务 3】私有云运维开发10 分

【题目 1】Ansible 服务部署:部署 MariaDB 集群2 分

使用OpenStack 私有云平台,创建 4 台系统为centos7.9 的云主机,其中一台作为 Ansible 的母机并命名为 ansible,另外三台云主机命名为 node1、node2、node3;使用这一台母机,编写 Ansible 脚本(在/root 目录下创建 example 目录作为 Ansible 工作目录,部署的入口文件命名为 cscc_install.yaml ) , 对其他三台云主机进行安装高可用数据库集群 (MariaDB_Galera_cluster,数据库密码设置为 123456)的操作(所需的安装包在 HTTP 服务中)。完成后提交 Ansible 节点的用户名、密码和 IP 地址到答题框。(考试系统会连接到你的Ansible 节点,去执行 Ansible 脚本,请准备好 Ansible 运行环境,以便考试系统访问)

(1)环境准备

节点 地址

ansible 192.168.100.10

node1 192.168.100.20

node2 192.168.100.30

node3 192.168.100.40

(2)环境配置

root@localhost \~# hostnamectl set-hostname ansible

root@localhost \~# su

root@ansible \~#

root@localhost \~# hostnamectl set-hostname node1

root@localhost \~# su

root@node1 \~#

root@localhost \~# hostnamectl set-hostname node2

root@localhost \~# su

root@node2 \~#

root@localhost \~# hostnamectl set-hostname node3

root@localhost \~# su

root@node3 \~#

将ip地址映射成主机名(其他3台节点配置一样,此处省略)

root@ansible \~# vi /etc/hosts

192.168.100.10 ansible

192.168.100.20 node1

192.168.100.30 node2

192.168.100.40 node3

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4

::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

#关闭防火墙和selinux(其他3台节点配置一样,此处省略)

root@ansible \~# systemctl stop firewalld && setenforce 0

ansible节点部署ansible服务(通过CRT远程工具将提供的ansible软件包上传到ansible节点)

root@ansible \~# tar -xvf ansible.tar.gz

#删除centos自带的源并配置本地yum源安装ansible服务

root@ansible \~# mv /etc/yum.repos.d/* /home/

root@ansible \~# vi /etc/yum.repos.d/local.repo

ansible

name=ansible

baseurl=file:///root/ansible

gpgcheck=0

enabled=1

root@ansible \~# yum install ansible -y

#检查是否安装完成

root@ansible \~# ansible --version

ansible 2.9.10

config file = /etc/ansible/ansible.cfg

configured module search path = u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'

ansible python module location = /usr/lib/python2.7/site-packages/ansible

executable location = /usr/bin/ansible

python version = 2.7.5 (default, Oct 14 2020, 14:45:30) GCC 4.8.5 20150623 (Red Hat 4.8.5-44)

(3)设置免密

root@ansible \~# ssh-keygen

Generating public/private rsa key pair.

Enter file in which to save the key (/root/.ssh/id_rsa):

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /root/.ssh/id_rsa.

Your public key has been saved in /root/.ssh/id_rsa.pub.

The key fingerprint is:

SHA256:svV0oqhTRNGB/tH37Xi49/OUg+AFu2XlxcKhsyXm+wI root@ansible

The key's randomart image is:

±--RSA 2048----+

| .+... . |

| o . o o |

| o . .= +.o|

| o . .o+=o...|

| ...S.o++= o |

| .=.+Eo*.o o|

| .o . .+... .|
| ... ...oo=|
| ... .o+
|

±---SHA256-----+

root@ansible \~# ssh-copy-id root@node1

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"

The authenticity of host 'node1 (192.168.100.20)' can't be established.

ECDSA key fingerprint is SHA256:sGY4R7darwNovS7pGeQNm9FzQjanFFmnwJHO5PRo0RE.

ECDSA key fingerprint is MD5:fa:5d:85:af:69:0d:63:78:ac:4e:9a:5b:c1:a6:b2:60.

Are you sure you want to continue connecting (yes/no)? yes

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed

/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

root@node1's password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'root@node1'"

and check to make sure that only the key(s) you wanted were added.

root@ansible \~# ssh-copy-id root@node2

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"

The authenticity of host 'node2 (192.168.100.30)' can't be established.

ECDSA key fingerprint is SHA256:sGY4R7darwNovS7pGeQNm9FzQjanFFmnwJHO5PRo0RE.

ECDSA key fingerprint is MD5:fa:5d:85:af:69:0d:63:78:ac:4e:9a:5b:c1:a6:b2:60.

Are you sure you want to continue connecting (yes/no)? yes

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed

/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

root@node2's password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'root@node2'"

and check to make sure that only the key(s) you wanted were added.

root@ansible \~# ssh-copy-id root@node3

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"

The authenticity of host 'node3 (192.168.100.40)' can't be established.

ECDSA key fingerprint is SHA256:sGY4R7darwNovS7pGeQNm9FzQjanFFmnwJHO5PRo0RE.

ECDSA key fingerprint is MD5:fa:5d:85:af:69:0d:63:78:ac:4e:9a:5b:c1:a6:b2:60.

Are you sure you want to continue connecting (yes/no)? yes

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed

/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

root@node3's password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'root@node3'"

and check to make sure that only the key(s) you wanted were added.

(4)修改ansible文件配置组

root@ansible \~# vi /etc/ansible/hosts

node

node1

node2

node3

node1

node1

node2

node2

node3

node3

#解压mariadb.tar软件包将mariadb-repo源拷贝到node1,node2,node3节点的/root目录下

root@ansible \~# tar -xvf mariadb.tar

mariadb/

mariadb/mariadb-repo.tar.gz

mariadb/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

mariadb/schema.xml

root@ansible \~# tar -xvf mariadb/mariadb-repo.tar.gz

root@ansible \~# scp -r mariadb-repo/ root@node1:/root

root@ansible \~# scp -r mariadb-repo/ root@node2:/root

root@ansible \~# scp -r mariadb-repo/ root@node3:/root

(5)创建ansible执行的工作目录编写执行playbook剧本的相关文件

root@ansible \~# mkdir cscc_galera(应该是example目录)

root@ansible \~# cd cscc_galera/

#创建local.repo文件

root@ansible cscc_galera# vi local.repo

centos

name=centos

baseurl=file:///opt/centos #自行挂载centos7.9镜像到/opt目录

gpgcheck=0

enabled=1

mariadb

name=mariadb

baseurl=file:///root/mariadb-repo

gpgcheck=0

enabled=1

#创建server.cnf文件

root@ansible cscc_galera# vi server.cnf

server

mysqld

galera

wsrep_on=ON

wsrep_provider=/usr/lib64/galera/libgalera_smm.so

wsrep_cluster_address=gcomm://node1,node2,node3

binlog_format=row

default_storage_engine=InnoDB

innodb_autoinc_lock_mode=2

bind-address=0.0.0.0

wsrep_slave_threads=1

innodb_flush_log_at_trx_commit=0

embedded

mariadb

mariadb-10.3

#创建playbook剧本文件

root@ansible cscc_galera# vi install_galera.yaml(应该是cscc_install.yaml)

  • hosts: all
    remote_user: root
    tasks:
    • name: rm repo
      shell: rm -rf /etc/yum.repos.d/*
    • name: copy repo
      copy: src=local.repo dest=/etc/yum.repos.d/
    • name: install mariadb
      yum: name=mariadb-server
    • name: start mariadb
      service: name=mariadb state=started enabled=yes
    • name: init_mysql
      shell: mysqladmin -uroot password 123456
    • name: stop mariadb
      service: name=mariadb state=stopped
    • name: copy server.cnf
      copy: src=server.cnf dest=/etc/my.cnf.d/server.cnf
  • hosts: node1
    remote_user: root
    tasks:
    • name: start mariadb
      shell: /usr/sbin/mysqld --wsrep-new-cluster -u root &
  • hosts: node2,node3
    remote_user: root
    tasks:
    • name: start mariadb
      shell: systemctl start mariadb
      (6)执行入口文件
      root@ansible cscc_galera# ansible-playbook install_galera.yaml
      WARNING: Found both group and host with same name: node1
      WARNING: Found both group and host with same name: node3
      WARNING: Found both group and host with same name: node2

PLAY all *******************************************************************************************************

TASK Gathering Facts *******************************************************************************************

ok: node3

ok: node2

ok: node1

TASK rm repo ***************************************************************************************************

WARNING: Consider using the file module with state=absent rather than running 'rm'. If you need to use command

because file is insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in

ansible.cfg to get rid of this message.

changed: node2

changed: node3

changed: node1

TASK copy repo *************************************************************************************************

changed: node3

changed: node2

changed: node1

TASK install mariadb *******************************************************************************************

changed: node2

changed: node3

changed: node1

TASK start mariadb *********************************************************************************************

changed: node1

changed: node2

changed: node3

TASK init_mysql ************************************************************************************************

changed: node2

changed: node1

changed: node3

TASK stop mariadb **********************************************************************************************

changed: node1

changed: node2

changed: node3

TASK copy server.cnf **********************************************************************************************

changed: node1

changed: node2

changed: node3

PLAY node1 *****************************************************************************************************

TASK Gathering Facts *******************************************************************************************

ok: node1

TASK start mariadb *********************************************************************************************

changed: node1

PLAY node2,node3 ***********************************************************************************************

TASK Gathering Facts *******************************************************************************************

ok: node2

ok: node3

TASK start mariadb *********************************************************************************************

changed: node2

changed: node3

PLAY RECAP *******************************************************************************************************

node1 : ok=9 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

node2 : ok=9 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

node3 : ok=9 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

root@ansible cscc_galera#

(7)验证,检查wsrep_cluster_size的值是否为3/wsrep_ready的状态是否为ON

root@ansible cscc_galera# ssh node1

Last login: Fri Aug 26 05:01:52 2022 from 192.168.100.1

root@node1 \~# mysql -uroot -p123456

Welcome to the MariaDB monitor. Commands end with ; or \g.

Your MariaDB connection id is 10

Server version: 10.3.23-MariaDB MariaDB Server

Copyright © 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB (none)> show status like 'wsrep_cluster_size';

±-------------------±------+

| Variable_name | Value |

±-------------------±------+

| wsrep_cluster_size | 3 |

±-------------------±------+

1 row in set (0.001 sec)

MariaDB (none)> show status like 'wsrep_ready';

±--------------±------+

| Variable_name | Value |

±--------------±------+

| wsrep_ready | ON |

±--------------±------+

1 row in set (0.001 sec)

MariaDB (none)>

1.执行yaml 文件正确计 0.5 分

2.检查数据库集群部署正确计 1 分

3.检查数据库集群数量为 3 正确计 0.5 分

【题目 2】Ansible 服务部署:部署ELK 集群服务2 分

使用赛项提供的OpenStack 私有云平台,创建三台 CentOS7.9 系统的云主机分别命名为elk-1、elk-2 和elk-3,Ansible 主机可以使用上一题的环境。要求Ansible 节点编写剧本,执行 Ansible 剧本可以在这三个节点部署 ELK 集群服务(在/root 目录下创建 install_elk 目录作为 ansible 工作目录,部署的入口文件命名为 install_elk.yaml)。具体要求为三个节点均安装Elasticserach 服务并配置为 Elasticserach 集群;kibana 安装在第一个节点;Logstash 安装在第二个节点。(需要用到的软件包在 HTTP 服务下)完成后提交 ansible 节点的用户名、密码和 IP 地址到答题框。(考试系统会连接到 ansible 节点,执行 ansible 脚本,准备好环境, 以便考试系统访问)

1.执行yaml 文件正确计 0.5 分

2.检查 ELK 服务部署正确计 1.5 分

(1)配置主机映射:

修改当前节点主机名为ansible,并修改ansible节点主机映射,命令如下:

root@localhost \~# hostnamectl set-hostname ansible

root@localhost \~# bash

root@ansible \~# cat /etc/hosts

172.128.11.162 ansible

172.128.11.217 node1

172.128.11.170 node2

172.128.11.248 node3

配置免密访问,虚拟机root用户密码为000000,命令如下:(考试的时候命名为elk-1、elk-2 和elk-3)

root@ansible \~# ssh-keygen

root@ansible \~# ssh-copy-id node1

root@ansible \~# ssh-copy-id node2

root@ansible \~# ssh-copy-id node3

将ansible节点的域名解析文件复制给安装Elasticsearch集群服务的三个节点,命令如下:

root@ansible \~# scp /etc/hosts node1:/etc/

root@ansible \~# scp /etc/hosts node2:/etc/

root@ansible \~# scp /etc/hosts node3:/etc/

关闭ansible节点的防火墙和Selinux配置(如已关闭,则不需要操作),命令如下:

root@ansible \~# setenforce 0

(2)软件包下载及yum源配置

将提供的Elasticsearch、Kibana以及Logstash软件包下载至ansible节点/root目录下,并将相应服务的软件包拷贝至不同节点。

root@ansible \~# curl -O http://mirrors.douxuedu.com/competition/Ansible.tar.gz

root@ansible \~# tar -zxvf Ansible.tar.gz

将Elasticsearch软件包拷贝至三个节点,将Kibana软件包拷贝至node1节点,将Logstash软件包拷贝至node2节点,命令如下:

root@ansible \~# scp elasticsearch-6.0.0.rpm node1:/root/

root@ansible \~# scp elasticsearch-6.0.0.rpm node2:/root/

root@ansible \~# scp elasticsearch-6.0.0.rpm node3:/root/

root@ansible \~# scp kibana-6.0.0-x86_64.rpm node1:/root/

root@ansible \~# scp kibana-6.0.0-x86_64.rpm node2:/root/

root@ansible \~# scp kibana-6.0.0-x86_64.rpm node3:/root/

root@ansible \~# scp logstash-6.0.0.rpm node1:/root/

root@ansible \~# scp logstash-6.0.0.rpm node2:/root/

root@ansible \~# scp logstash-6.0.0.rpm node3:/root/

将软件包ansible.tar.gz上传至ansible节点配置本地yum源,并安装Ansible:

root@ansible \~# tar -zxvf ansible.tar.gz -C /opt/

root@ansible \~# mv /etc/yum.repos.d/* /media/

root@ansible \~# vi /etc/yum.repos.d/local.repo

ansible

name=ansible

baseurl=file:///opt/ansible

gpgcheck=0

enabled=1

root@ansible \~# yum -y install ansible

(3)配置Ansible主机映射

创建示例目录,并配置Ansible主机映射。

root@ansible \~# mkdir example

root@ansible \~# cd example

root@ansible example# vi /etc/ansible/hosts

node1

172.128.11.217

node2

172.128.11.170

node3

172.128.11.248

使用CentOS-7-x86_64-DVD-2009.iso镜像文件作为安装库,将镜像挂载至/opt/centos,编写yum源文件,安装vsftpd服务,用于给远程主机安装Java。命令如下:

root@ansible example# curl -O http://mirrors.douxuedu.com/competition/CentOS-7-x86_64-DVD-2009.iso

root@ansible example# mkdir /opt/centos

root@ansible example# mount CentOS-7-x86_64-DVD-2009.iso /opt/centos/

root@ansible example# vi /etc/yum.repos.d/local.repo

ansible

name=ansible

baseurl=file:///opt/ansible

gpgcheck=0

enabled=1

centos

name=centos

baseurl=file:///opt/centos

gpgcheck=0

enabled=1

root@ansible example# yum install -y vsftpd

root@ansible example# vi /etc/vsftpd/vsftpd.conf

anon_root=/opt

root@ansible example# systemctl restart vsftpd

root@ansible example# vi ftp.repo

centos

name=centos

baseurl=ftp://172.128.11.162/centos/

gpgcheck=0

enabled=1

(4)安装Elasticsearch获取配置文件

安装Elasticsearch服务并编写node1节点配置文件,命令如下:

root@ansible example# rpm -ivh /root/elasticsearch-6.0.0.rpm

root@ansible example# cp -rf /etc/elasticsearch/elasticsearch.yml elk1.yml

root@ansible example# cat elk1.yml | grep -Ev "^KaTeX parse error: Expected group after '^' at position 2: |^̲#" cluster.name...|^#"

cluster.name: ELK

node.name: node2

node.master: false

node.data: true

path.data: /var/lib/elasticsearch

path.logs: /var/log/elasticsearch

network.host: 172.128.11.170

http.port: 9200

discovery.zen.ping.unicast.hosts: "node1","node2","node3"

编写node3节点配置文件,命令如下:

root@ansible example# cp elk1.yml elk3.yml

root@ansible example# cat elk3.yml | grep -Ev "$|#"

cluster.name: ELK

node.name: node3

node.master: false

node.data: true

path.data: /var/lib/elasticsearch

path.logs: /var/log/elasticsearch

network.host: 172.128.11.248

http.port: 9200

discovery.zen.ping.unicast.hosts: "node1","node2","node3"

(5)安装Kibana获取配置文件

安装Kibana服务并编写配置文件,命令如下:

root@ansible example# rpm -ivh /root/kibana-6.0.0-x86_64.rpm

root@ansible example# cp -rf /etc/kibana/kibana.yml .

root@ansible example# cat kibana.yml |grep -v ^#

server.port: 5601

server.host: "172.128.11.217"

elasticsearch.url: "http://172.128.11.217:9200"

(6)安装Logstash获取配置文件

安装Logstash服务并获取配置文件,命令如下:

root@ansible example# rpm -ivh /root/logstash-6.0.0.rpm

root@ansible example# cp -rf /etc/logstash/logstash.yml .

root@ansible example# vi logstash.yml

http.host: "172.128.11.170"

新建日志输出文件,内容如下:

root@ansible example# vi syslog.conf

input {

file {

path => "/var/log/messages" #指定文件的路径

type => "systemlog" #定义日志类型,可自定义

start_position => "beginning" #指定何时开始收集

stat_interval => "3"

}

}

output {

if type == "systemlog" {

elasticsearch {

hosts => "172.128.11.217:9200" #这里的地址为node1主机地址

index => "system-log-%{+YYYY.MM.dd}"

}

}

}

(7)编写剧本文件

安编写Playbook剧本文件,命令如下:

root@ansible example# vi cscc_install.yaml

  • hosts: all
    remote_user: root
    tasks:
    • name: rm repo
      shell: rm -rf /etc/yum.repos.d/*
    • name: copy repo
      copy: src=ftp.repo dest=/etc/yum.repos.d/
    • name: install java
      shell: yum -y install java-1.8.0-*
    • name: install elk
      shell: rpm -ivh elasticsearch-6.0.0.rpm
  • hosts: node1
    remote_user: root
    tasks:
    • name: copy config
      copy: src=elk1.yml dest=/etc/elasticsearch/elasticsearch.yml
    • name: daemon-reload
      shell: systemctl daemon-reload
    • name: start elk
      shell: systemctl start elasticsearch && systemctl enable elasticsearch
    • name: install kibana
      shell: rpm -ivh kibana-6.0.0-x86_64.rpm
    • name: copy config
      template: src=kibana.yml dest=/etc/kibana/kibana.yml
    • name: start kibana
      shell: systemctl start kibana && systemctl enable kibana
  • hosts: node2
    remote_user: root
    tasks:
    • name: copy config
      copy: src=elk2.yml dest=/etc/elasticsearch/elasticsearch.yml
    • name: daemon-reload
      shell: systemctl daemon-reload
    • name: start elk
      shell: systemctl start elasticsearch && systemctl enable elasticsearch
    • name: install logstash
      shell: rpm -ivh logstash-6.0.0.rpm
    • name: copy config
      copy: src=logstash.yml dest=/etc/logstash/logstash.yml
    • name: copy config
      copy: src=syslog.conf dest=/etc/logstash/conf.d/syslog.conf
  • hosts: node3
    remote_user: root
    tasks:
    • name: copy config
      copy: src=elk3.yml dest=/etc/elasticsearch/elasticsearch.yml
    • name: daemon-reload
      shell: systemctl daemon-reload
    • name: start elk
      shell: systemctl start elasticsearch && systemctl enable elasticsearch
      执行Playbook完成ELK集群的部署,命令如下:
      root@ansible example# ansible-playbook cscc_install.yaml
      执行结果如图2所示:

图2 执行结果

浏览器访问node1节点5601端口,http://172.128.11.217:5601/,如图3所示:

图3 部署成功

【题目 3】Python 运维开发:基于OpenStack Restful API 实现镜像上传1 分

使用OpenStack all-in-one 镜像,创建 OpenStack Python 运维开发环境。云主机的用户/ 密码为:"root/Abc@1234",OpenStack 的域名/账号/密码为:"demo/admin/000000"。 提示说明:python 脚本文件头建议加入"#encoding:utf-8"避免编码错误;测试脚本代码用 python3 命令执行与测试。 在 controller 节点的/root 目录下创建api_image_manager.py 脚本,编写 python 代码对接OpenStack API,完成镜像的创建与上传。创建之前查询是否存在"同名镜像",如果存在先删除该镜像。

(1)创建镜像:要求在 OpenStack 私有云平台中上传镜像cirros-0.3.4-x86_64-disk.img,名字为 cirros001,disk_format 为 qcow2,container_format 为bare。

(2)查询镜像:查询 cirros001 的详细信息,并以 json 格式文本输出到控制台。 完成后提交 OpenStack Python 运维开发环境Controller 节点的 IP 地址,用户名和密码提交。

1.执行api_image_manager.py 脚本,成功创建镜像,计 0.5 分

2.检查镜像状态正确,计 0.5 分

(1)基础环境准备,安装python3,已经需要的依赖

安装工具包

yum install gcc -y

yum install libffi-devel -y

yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make

安装python3

tar -xzvf Python-3.6.8.tgz

cd Python-3.6.8

./configure

make # 编译

make install # 编译安装

验证:

root@controller \~# python3

Python 3.6.8 (default, Oct 29 2023, 22:01:11)

GCC 4.8.5 20150623 (Red Hat 4.8.5-4) on linux

Type "help", "copyright", "credits" or "license" for more information.

root@ controller \~# python3 --version

Python 3.6.8

安装文件依赖包:

安装setuptools

tar -zxvf setuptools-41.1.0.post1.tar.gz

cd setuptools-41.1.0.post1/

python3 setup.py install

安装pip

tar -zxvf pip-19.2.2.tar.gz

cd pip-19.2.2

python3 setup.py install

验证pip

root@controller pip-19.2.2# pip -V

pip 19.2.2 from /usr/local/lib/python3.6/site-packages/pip-19.2.2-py3.6.egg/pip (python 3.6)

#使用提供的whl文件安装依赖

root@controller \~# cd Python-api

root@controller \~# pip3 install certifi-2019.11.28-py2.py3-none-any.whl

root@controller \~# pip3 install urllib3-1.25.11-py3-none-any.whl

root@controller \~# pip3 install idna-2.8-py2.py3-none-any.whl

root@controller \~# pip3 install chardet-3.0.4-py2.py3-none-any.whl

root@controller \~# pip3 install requests-2.24.0-py2.py3-none-any.whl

(2)代码实现

root@controller \~# vi api_image_manager.py

#encoding:utf-8

import requests,json,time

def get_auth_token(controller_ip,domain,name,password):

url = f"http://{controller_ip}:5000/v3/auth/tokens"

body = {

"auth": {

"identity": {

"methods": 'password',

"password": {

"user": {

"domain": {"name": domain},

"name": name,

"password": password,

}

}

},

"scope": {

"project": {

"domain": {"name": domain},

"name": name

}

}

}

}

headers = {

"Content-Type": "application/json"

}

token = requests.post(url,headers=headers,data=json.dumps(body)).headers'X-Subject-Token'

headers = {

"X-Auth-Token": token

}

print(f"token值为:{token}")

return headers

class image_manager:

def init (self,handers:dict,resUrl):

self.headers = handers

self.resUrl = resUrl

复制代码
def create_image(self,image_name,disk_format,container_format):
    body = {
        "name": image_name,
        "disk_format": disk_format,
        "container_format": container_format,
    }

    req = requests.post(self.resUrl,headers=self.headers,data=json.dumps(body)).text
    print(f"创建镜像的信息为:{req}")
    return req

def get_image_id(self,name):
    req = json.loads(requests.get(self.resUrl,headers=self.headers).text)
    for image in req['images']:
        if image['name'] == name:
            return image['id']
    return "NONE"

def upload_image(self,id,file_path:str):
    url = self.resUrl + "/" + id + "/file"
    self.headers["Content-Type"] = "application/octet-stream"
    req = requests.put(url,headers=self.headers,data=open(file_path,'rb').read())
    if req.status_code == 204:
        print("上传镜像成功",req.status_code)
    else:
        print("上传镜像失败",req.status_code)

    print(f"镜像上传信息:{req}")
    return req

def get_image(self,id):
    url = self.resUrl + "/" + id
    req = json.loads(requests.get(self.resUrl,headers=self.headers).text)
    print(f"获取到的镜像信息为:{req}")
    return req

def delete_image(self,id):
    url = self.resUrl + "/" + id
    req = requests.delete(url,headers=self.headers)
    print(f"删除信息:{req}")
    return req

if name == "main ":

controller_ip = "192.168.100.10"

domain = "demo"

name = "admin"

password = "000000"

headers = get_auth_token(controller_ip, domain, name, password)

print(headers)

image_m = image_manager(headers,f"http://{controller_ip}:9292/v2/images")

复制代码
#create
create_image = image_m.create_image("cirros001","qcow2","bare")

#get id
get_id = image_m.get_image_id("cirros001")
print(f"cirros001镜像ID为:{get_id}")

#upload
upload_image = image_m.upload_image(get_id,"/root/cirros-0.3.0-x86_64-disk.img ")

#get image
get_image = image_m.get_image(get_id)
with open("image_demo.json","w")as outfile:
    json.dump(get_image,outfile,indent=4)

【题目 4】Python 运维开发:基于 Openstack Python SDK 实现云主机创建1 分

使 用 已 建 好 的 OpenStack Python 运 维 开 发 环 境 ,在 /root 目 录 下 创 建sdk_server_manager.py 脚本,使用 python-openstacksdk Python 模块,完成云主机的创建和查询。创建之前查询是否存在"同名云主机",如果存在先删除该镜像。

(1)创建 1 台云主机:云主机信息如下:

云主机名称如下:server001

镜像文件:cirros-0.3.4-x86_64-disk.img

云主机类型:m1.tiny

网络等必要信息自己补充。

(2)查询云主机:查询云主机 server001 的详细信息,并以 json 格式文本输出到控制台。 完成后提交 OpenStack Python 运维开发环境 Controller 节点的 IP 地址,用户名和密码提交。

1.执行 sdk_server_manager.py 脚本,成功创建云主机,计 0.5 分

2.检查创建的云主机状态正确,计 0.5 分

(1)代码实现

创建云主机所需的镜像、类型、网络是用name来识别的,需要提前创建好

root@container \~# vi sdk_server_manager.py

#encoding:utf-8

import json,logging

import openstack

#文档地址

https://docs.openstack.org/openstacksdk/latest/user/index.html

def create_connection(auth_url, user_domain_name, username, password):

"""

建立连接

"""

return openstack.connect(

auth_url=auth_url,

user_domain_name=user_domain_name,

username=username,

password=password,

)

#user Manager

参见文档

https://docs.openstack.org/openstacksdk/latest/user/guides/identity.html

#openstack.connection.Connection

#云主机管理

class server_manager:

复制代码
def __init__(self, connect):
    self.connect = connect

def list_servers(self):
    """
    查询所有云主机.
    """
    #to json
    items = self.connect.compute.servers()
    server_jsons = {}
    for server in items:
        server_jsons[server['name']] = server
    # return ""
    return items# json.dumps(server_jsons,indent=2,skipkeys=True)

def create_server(self, server_name, image_name, flavor_name,networ_name):
    image = self.connect.compute.find_image(image_name)
    flavor = self.connect.compute.find_flavor(flavor_name)
    network = self.connect.network.find_network(networ_name)
    server = self.connect.compute.create_server(
        name=server_name, image_id=image.id, flavor_id=flavor.id,
        networks=[{"uuid": network.id}])
    result = self.connect.compute.wait_for_server(server)
    return result#json.dumps(result,indent=2,skipkeys=True)

def delete_server(self, server_name):
    """
    删除云主机
    """
    server = self.connect.compute.find_server(server_name)
    result = self.connect.compute.delete_server(server)
    return json.dumps(result, indent=2, skipkeys=True)

def get_server(self, server_name):
    """
    获取云主机
    """
    server = self.connect.compute.find_server(server_name)
    if server:
        return json.dumps(server, indent=2, skipkeys=True)
    else:
        return None

class image_manager:

复制代码
def __init__(self, connect):
    self.connect = connect

def list_images(self):
    """
    查询所有镜像
    """
    #to json
    items = self.connect.compute.images()
    images_jsons = {}
    for image in items:
        images_jsons[image['name']] = image
    return json.dumps(images_jsons,indent=2)

def get_image(self, image_name:str):
    """
    查询镜像
    """
    #to json
    image = self.connect.compute.find_image(image_name)

    return json.dumps(image,indent=2)

class flavor_manager:

复制代码
def __init__(self, connect):
    self.connect = connect

def list_flavors(self):
    """
    查询所有云主机类型
    """
    #to json
    items = self.connect.compute.flavors()
    flavors_jsons = {}
    for flavor in items:
        flavors_jsons[flavor['name']] = flavor
    return json.dumps(flavors_jsons,indent=2)

def get_flavor(self, flavor_name:str):
    """
    根据名称获取云主机类.
    """
    #to json
    flavor = self.connect.compute.find_flavor(flavor_name)
    return json.dumps(flavor,indent=2)

class network_manager:

复制代码
def __init__(self, connect):
    self.connect = connect

def list_networks(self):
    """
    查询所有网络.
    """
    #to json
    items = self.connect.network.networks()
    items_jsons = {}
    for network in items:
        items_jsons[network['name']] = network
    return json.dumps(items_jsons,indent=2)

def get_network(self, network_name:str):
    """
    跟名称查询网络.
    """
    #to json
    flavor = self.connect.compute.find_network(network_name)
    return json.dumps(flavor,indent=2)

if name == 'main':

复制代码
# Initialize connection(通过配置文件)
# controller_ip = "10.24.2.22"
controller_ip = "controller"
auth_url = "http://controller:5000/v3/"
username = "admin"
password = "000000"
user_domain_name = 'demo'

conn = create_connection(auth_url, user_domain_name, username, password)

sdk_m = server_manager(conn)
server = sdk_m.get_server("server001")
if server:
    result = sdk_m.delete_server("server001")
    print("servers:", result)

#2 创建云主机
print("creat server--------")
servers = sdk_m.create_server("server001","cirros001","m1.tiny","net")
print("servers:", servers)

#6 查询云主机
server_info = sdk_m.get_server("server001")

print(server_info)

创建网络,命令如下:

root@controller \~# source /etc/keystone/admin-openrc.sh

root@controller \~# openstack network create --provider-network-type vlan --provider-physical-network provider --provider-segment 10 --project admin net

root@controller \~# NET="111.111.10.0/24"

root@controller \~# ID=(openstack network list --project admin \|grep -v ID \|grep net \|awk -F "\| " {'print 2'})

root@controller \~# openstack subnet create --project admin --subnet-range NET --dhcp --network ID ext-subnet

执行sdk_server_manager.py文件:

root@controller \~# python3 sdk_server_manager.py

-----------------------------------------执行结果-----------------------------

#创建云主机的信息为:{"server": {"security_groups": {"name": "default"}, "OS-DCF:diskConfig": "MANUAL", "id": "f295eb8d-52a0-4e21-ba86-6

4ba8c3e6359", "links": [{"href": "http://192.168.106.10:8774/v2.1/servers/f295eb8d-52a0-4e21-ba86-64ba8c3e6359", "rel": "self"}, {"href":

"http://192.168.106.10:8774/servers/f295eb8d-52a0-4e21-ba86-64ba8c3e6359", "rel": "bookmark"}], "adminPass": "oTs5jHFwkbWy"}}

【题目 5】Python 运维开发:云主机类型管理的命令行工具开发2 分

使用已建好的 OpenStack Python 运维开发环境,在/root 目录下创建 flavor_manager.py 脚本,完成云主机类型的管理,flavor_manager.py 程序支持命令行参数执行。提示说明:Python 标准库argparse 模块,可以提供命令行参数的解析。要求如下:

(1)程序支持根据命令行参数,创建 1 个多云主机类型。返回 response。位置参数"create",表示创建; 参数"-n"支持指定 flavor 名称,数据类型为字符串类型; 参数"-m"支持指定内存大小,数据类型为 int,单位 M; 参数"-v"支持指定虚拟 cpu 个数,数据类型为 int; 参数"-d"支持磁盘大小,内存大小类型为 int,单位 G; 参数"-id"支持指定 ID,类型为字符串。 参考运行实例: python3 flavor_manager.py create -n flavor_small -m 1024 -v 1 -d 10 -id 100000

(2)程序支持查询目前 admin 账号下所有的云主机类型。位置参数"getall",表示查询所有云主机类型; 查询结果,以 json 格式输出到控制台。参考执行实例如下: python3 flavor_manager.py getall

(3)支持查询给定具体名称的云主机类型查询。位置参数"get",表示查询 1 个云主机类型; 参数"-id"支持指定 ID 查询,类型为 string。 控制台以 json 格式输出创建结果。 参考执行实例如下: python3 flavor_manager.py get -id 100000

(4)支持删除指定的 ID 云主机类型。 位置参数"delete",表示删除一个云主机类型; 参数"-id"支持指定 ID 查询,返回 response,控制台输出response。参考执行实例如下: python3 flavor_manager.py delete -id 100001

暂无

1.执行 flavor_manager.py 脚本,指定 create 和配置参数,成功创建 1 个云主机类型,计 0.5 分; 2.执行 flavor_manager.py 脚本,指定 getall 参数,成功查询所有云主机类型,计 0.5 分;

3.执行 flavor_manager.py 脚本,指定 get 和配置参数,成功查询具体名称的云主机类型,计 0.5 分;

4.执行 flavor_manager.py 脚本,指定 delete 和配置参数,成功删除指定 ID 云主机类型,计 0.5 分。

api_flavor_manager.py:

import requests,json,time

import logging

#-----------logger-----------

#get logger

logger = logging.getLogger(name)

level

logger.setLevel(logging.DEBUG)

format

format = logging.Formatter('%(asctime)s %(message)s')

to console

stream_handler = logging.StreamHandler()

stream_handler .setFormatter(format)

logger.addHandler(stream_handler )

#-----------logger-----------

def get_auth_token(controller_ip, domain, user, password):

复制代码
try:
    url = f"http://{controller_ip}:5000/v3/auth/tokens"
    body = {
                "auth": {
                    "identity": {
                        "methods": [
                            "password"
                        ],
                        "password": {
                            "user": {
                                "domain": {
                                    "name": domain
                                },
                                "name": user,
                                "password": password
                            }
                        }
                    },
                    "scope": {
                        "project": {
                            "domain": {
                                "name": domain
                            },
                            "name": user
                        }
                    }
                }
            }

    headers = {
        "Content-Type": "application/json",
    }
    print(body)
    Token = requests.post(url, data=json.dumps(body), headers=headers).headers['X-Subject-Token']

    headers = {
        "X-Auth-Token": Token
    }
    logger.debug(f"获取Token值:{str(Token)}")
    return headers
except Exception as e:
    logger.error(f"获取Token值失败,请检查访问云主机控制节点IP是否正确?输出错误信息如下:{str(e)}")
    exit(0)

class flavor_manager:

复制代码
def __init__(self,handers:dict,resUrl:str):
    self.headers=handers
    self.resUrl=resUrl
#创建flavor类型
def create_flavor(self,flavor_name:str,ram,vcpus,disk,id):
    self.headers['Content-Type']="application/json"
    body={
        "flavor":{
            "name":flavor_name,
            "ram":ram,
            "vcpus":vcpus,
            "disk":disk,
            "id":id,
        }
    }
    logger.debug(f"创建flavor请求body:{str(body)}")
    status_code = requests.post(self.resUrl, data=json.dumps(body), headers=self.headers).text
    logger.debug(f"返回状态:{str(status_code)}")
    return  status_code

#获取all flavors
def get_flavors(self):
    result = json.loads(requests.get(self.resUrl,headers=self.headers).text)
    logger.debug(f"返回信息:{str(result)}")
    return result
    # 获取flavor_id

def get_flavor(self, id:str):
    api_url = self.resUrl + "/"+id
    result = json.loads(requests.get(api_url, headers=self.headers).text)
    logger.debug(f"返回信息:{str(result)}")
    return result

def delete_flavor(self, id:str):
    api_url = self.resUrl + "/"+id
    response = requests.delete(api_url, headers=self.headers)

    #Normal response codes: 202 without return text
    if response.status_code == 202:
        return {"itemDeletedSuccess": response.status_code}

    result = json.loads(response.text)
    logger.debug(f"返回信息:{str(result)}")
    return result

#http://192.168.200.226:8774/v2.1/ get apis version infomation.
def update_flavor_desc(self, id: str, desc:str):
    # 特别注意:This API is available starting with microversion 2.55.
    self.headers['X-OpenStack-Nova-API-Version'] = "2.55"

    self.headers['Content-Type'] = "application/json"
    body = {
        "flavor": {
            "description": desc
        }
    }

    api_url = self.resUrl + "/" + id
    response = requests.put(api_url, data=json.dumps(body), headers=self.headers)
    # Normal response codes: 202 without return text
    if response.status_code == 202:
        return {"itemUpdateSuccess": response.status_code}

    result = json.loads(response.text)
    logger.debug(f"返回信息:{str(result)}")
    return result

if name == 'main ':

controller_ip = "controller"

domain = "demo"

user = "admin"

password = "000000"

headers = get_auth_token(controller_ip, domain, user, password)

flavor_m = flavor_manager(headers, f"http://{controller_ip}:8774/v2.1/flavors")

复制代码
#1 查所有
flavors = flavor_m.get_flavors()

print("查询所有flavors:", flavors)

flavor_manager.py:

#encoding:utf-8

import argparse

import api_flavor_manager

1. openstack allinone (controller ) credentials

host ip address

controller_ip = "10.24.2.22"

controller_ip = "controller"

domain name

domain = "demo"

user name

user = "admin"

user password

password = "000000"

headers = api_flavor_manager.get_auth_token(controller_ip,domain,user,password)

print("headers:", headers)

#. get token

flavor_m = api_flavor_manager.flavor_manager(headers, "http://controller:8774/v2.1/flavors")

def define_args(parser):

"""

定义程序支持的args

:return:

"""

parser = argparse.ArgumentParser()

复制代码
#增加控制命令(postion 位置参数,必须)
parser.add_argument('command',
                    help='Resource command name',
                    type=str)
# parser.add_argument('delete',
#                     help='delete a resource',
#                     type=str)
#可选参数(可有可无)
parser.add_argument('-n', '--name',  # 可选参数,删除的名称
                    help='The Name of the resource',  # 输入-h展示
                    type=str)
parser.add_argument('-o', '--output',  # 可选参数,删除的名称
                    help='The output file path ',  # 输入-h展示
                    type=str)
parser.add_argument('-m', '--memory',  # 可选参数,删除的名称
                    help='The Name of the resource',  # 输入-h展示
                    type=str)
parser.add_argument('-v', '--vcpu',  # 可选参数,删除的名称
                    help='The Name of the resource',  # 输入-h展示
                    type=str)
parser.add_argument('-d', '--disk',  # 可选参数,删除的名称
                    help='The Name of the resource',  # 输入-h展示
                    type=str)
parser.add_argument('-id', '--id',  # 可选参数,删除的名称
                    help='The Name of the resource',  # 输入-h展示
                    type=str)

def parse_args(parser):

复制代码
args = parser.parse_args()
if args.command:
    if args.command == "create":
        print("create some thing")
        create_flavor(args)
    elif args.command == "getall":
        print("getall some thing")
        getall_flavor(args)
    elif args.command == "get":
        print("get some thing")
        get_flavor(args)
    elif args.command == "delete":
        print("delete some thing")
        delete_flavor(args)
    else:
        print("Note support command name!")

def create_flavor(args):

print('Provided command value is %r.' % args.command)

print('Provided name value is %r.' % args.name)

print('Provided memory value is %r.' % args.memory)

print('Provided vcpu value is %r.' % args.vcpu)

print('Provided disk value is %r.' % args.disk)

print('Provided id value is %r.' % args.id)

result = flavor_m.create_flavor(args.name,args.memory,args.vcpu,args.disk,args.id)

print(result)

def delete_flavor(args):

print('Provided command value is %r.' % args.command)

print('Provided id value is %r.' % args.id)

result = flavor_m.delete_flavor(args.id)

print(result)

def getall_flavor(args):

print('Provided command value is %r.' % args.command)

result = flavor_m.get_flavors()

print(result)

def get_flavor(args):

print('Provided command value is %r.' % args.command)

print('Provided id value is %r.' % args.id)

result = flavor_m.get_flavor(args.id)

print(result)

if name == 'main ':

parser = argparse.ArgumentParser()

define_args(parser)

parse_args(parser)

-------------------------------------------执行结果--------------------------------

{'auth': {'identity': {'methods': 'password', 'password': {'user': {'domain': {'name': 'demo'}, 'name': 'admin', 'password': '000000'}}}, 'scope': {'project': {'domain': {'name': 'demo'}, 'name': 'admin'}}}}

【题目 6】Python 运维开发:用户管理的命令行工具开发2 分

使用已建好的OpenStack Python 运维开发环境,在/root 目录下创建 user_manager.py 脚本,完成用户管理功能开发,user_manager.py 程序支持命令行带参数执行。 提示说明:Python 标准库argparse 模块,可以提供命令行参数的解析。

(1)程序支持根据命令行参数,创建 1 个用户。位置参数"create",表示创建; 参数"-i 或--input",格式为 json 格式文本用户数据。查询结果,以 json 格式输出到控制台。 参考执行实例如下: python3 user_manager.py create --input '{ "name": "user01", "password": "000000", "description": "description" } '

(2)支持查询给定具体名称的用户查询。 位置参数"get",表示查询 1 个用户; 参数"-n 或 --name"支持指定名称查询,类型为 string。 参数"-o 或 output"支持查询该用户信息输出到文件,格式为json 格式。参考执行实例如下: python3 user_manager.py get --name user01-o user.json

(3)程序支持查询目前 admin 账号下所有的用户。位置参数"getall",表示查询所有用户; 参数"-o 或--output"支持输出到文件,格式为 yaml 格式。参考执行实例如下: python3 user_manager.py getall -o openstack_all_user.yaml

(4)支持删除指定的名称的用户。 位置参数"delete",表示删除一个用户;返回 response,通过控制台输出。参数"-n 或--name"支持指定名称查询,类型为 string。 参考执行实例如下: python3 user_manager.py delete -name user01

暂无

1.执行user_manager.py 脚本,指定 create 和配置参数,成功创建 1 个用户,计 0.5 分;

2.执行user_manager.py 脚本,指定 get 和配置参数,成功查询具体名称的用户,计 0.5 分;

3.执行user_manager.py 脚本,指定 getall 和配置参数,成功查询 admin 账号下的所有用户, 计 0.5 分;

4.执行user_manager.py 脚本,指定 delete 和配置参数,成功删除指定名称的用户,计 0.5 分

api_user_manager.py:

encoding:utf-8

import requests, json, time

import logging

-----------logger-----------

get logger

logger = logging.getLogger(name)

level

logger.setLevel(logging.DEBUG)

format

format = logging.Formatter('%(asctime)s %(message)s')

to console

stream_handler = logging.StreamHandler()

stream_handler.setFormatter(format)

logger.addHandler(stream_handler)

-----------logger-----------

def get_auth_token(controller_ip, domain, user, password):

'''

:param controller_ip: openstack master ip address

:param domain: current user's domain

:param user: user name

:param password: user password

:return: keystoen auth Token for current user.

'''

复制代码
try:
    url = "http://controller:5000/v3/auth/tokens"
    body = {
        "auth": {
            "identity": {
                "methods": [
                    "password"
                ],
                "password": {
                    "user": {
                        "domain": {
                            "name": domain
                        },
                        "name": user,
                        "password": password
                    }
                }
            },
            "scope": {
                "project": {
                    "domain": {
                        "name": domain
                    },
                    "name": user
                }
            }
        }
    }

    headers = {
        "Content-Type": "application/json",
    }
    print(body)
    Token = requests.post(url, data=json.dumps(body), headers=headers).headers['X-Subject-Token']

    headers = {
        "X-Auth-Token": Token
    }
    logger.debug(f"获取Token值:{str(Token)}")
    return headers
except Exception as e:
    logger.error(f"获取Token值失败,请检查访问云主机控制节点IP是否正确?输出错误信息如下:{str(e)}")
    exit(0)

用户管理

https://docs.openstack.org/api-ref/identity/v3/index.html#users

class user_manager:

def init (self, handers: dict, resUrl: str):

self.headers = handers

self.resUrl = resUrl

复制代码
#      POST  /v3/users  Create user
def create_users(self, user_name, password: str, desc: str):
    """
    create a user with name and password and description.
    """

    body = {
        "user": {
            "name": user_name,
            "password": password,
            "description": desc,
        }
    }
    status_code = requests.post(self.resUrl, data=json.dumps(body), headers=self.headers).text
    logger.debug(f"返回状态:{str(status_code)}")
    return status_code

# /v3/users    # List all users
def get_users(self):
    """
    get user
    """
    status_code = requests.get(self.resUrl, headers=self.headers).text
    logger.debug(f"返回状态:{str(status_code)}")
    return status_code

def get_user_id(self, user_name):
    """
    get user id by name.
    """
    result = json.loads(requests.get(self.resUrl, headers=self.headers).text)
    user_name = user_name
    for item in result['users']:
        if item['name'] == user_name:
            return item['id']
    return "NONE"

def get_user(self, id: str):
    """
    get a flavor by id.
    """
    api_url = self.resUrl + "/" + id
    result = json.loads(requests.get(api_url, headers=self.headers).text)
    logger.debug(f"返回信息:{str(result)}")
    return result

def delete_user(self, name: str):
    """
     delete a user by id.
     """
    id = self.get_user_id(name)
    api_url = self.resUrl + "/" + id
    response = requests.delete(api_url, headers=self.headers)

    # 204 - No Content  The server has fulfilled the request.
    if response.status_code == 204:
        return {"User itemDeletedSuccess": response.status_code}

    result = json.loads(response.text)
    logger.debug(f"返回信息:{str(result)}")
    return result

    # http://192.168.200.226:8774/v2.1/ get apis version infomation.

def update_User_password(self, id: str, original_password: str, new_password: str):
    """
    update a flavor desc by id.

    """
    self.headers['Content-Type'] = "application/json"
    body = {
        "user": {
            "password": new_password,
            "original_password": original_password
        }
    }

    api_url = self.resUrl + "/" + id + "/password"
    response = requests.post(api_url, data=json.dumps(body), headers=self.headers)
    # Normal response codes: 204 without return text
    if response.status_code == 204:
        return {"item Update Password Success": response.status_code}

    result = json.loads(response.text)
    logger.debug(f"返回信息:{str(result)}")
    return result

if name == 'main ':

1. openstack allinone (controller ) credentials

host ip address

controller_ip = "10.24.2.22"

controller_ip = "controller"

controller_ip = "10.24.2.22"

domain name

domain = "demo"

user name

user = "admin"

user password

password = "000000"

headers = get_auth_token(controller_ip, domain, user, password)

print("headers:", headers)

get all user

user_m = user_manager(headers, "http://controller:5000/v3/users")

1 查询所有

users = user_m.get_users()

print("查询所有users:", users)

user_manager.py:

#encoding:utf-8

import argparse

import api_user_manager

import json

import csv

import yaml

1. openstack allinone (controller ) credentials

host ip address

controller_ip = "10.24.2.22"

controller_ip = "controller"

controller_ip = "10.24.2.22"

domain name

domain = "demo"

user name

user = "admin"

user password

password = "000000"

headers = api_user_manager.get_auth_token(controller_ip, domain, user, password)

print("headers:", headers)

get all user

user_m = api_user_manager.user_manager(headers, "http://controller:5000/v3/users")

print("-----------begin-----------------")

def define_args(parser):

"""

定义程序支持的args

:return:

"""

parser = argparse.ArgumentParser()

复制代码
#增加控制命令(postion 位置参数,必须)
parser.add_argument('command',
                    help='Resource command name',
                    type=str)
# parser.add_argument('delete',
#                     help='delete a resource',
#                     type=str)
#可选参数(可有可无)
parser.add_argument('-n', '--name',  # 可选参数,删除的名称
                    help='The Name of the resource',  # 输入-h展示
                    type=str)
parser.add_argument('-i', '--input',  # 可选参数,删除的名称
                    help='The input json format text ',  # 输入-h展示
                    type=str)
parser.add_argument('-o', '--output',  # 可选参数,删除的名称
                    help='The output file path ',  # 输入-h展示
                    type=str)

def parse_args(parser):

args = parser.parse_args()

if args.command:

if args.command == "create":

print("create some thing")

create_user(args)

elif args.command == "getall":

print("getall some thing")

getall_users(args)

elif args.command == "get":

print("get some thing")

get_user(args)

elif args.command == "delete":

print("delete some thing")

delete_user(args)

else:

print("Note support command name!")

def create_user(args):

print('Provided command value is %r.' % args.command)

print('Provided input value is %r.' % args.input)

print('Provided output value is %r.' % args.output)

output_file = args.output

user_name, password: str, desc: str):

user_dict = json.loads(args.input)

result = user_m.create_users(user_dict"name",user_dict"password",user_dict"description")

复制代码
# 写出json文件
print("--------write to json---------:", result)
print(result)

def delete_user(args):

print('Provided command value is %r.' % args.command)

print('Provided input value is %r.' % args.input)

print('Provided output value is %r.' % args.output)

result = user_m.delete_user(args.name)

print(result)

def getall_users(args):

print('Provided command value is %r.' % args.command)

print('Provided input value is %r.' % args.input)

print('Provided output value is %r.' % args.output)

print(type(args.input))

result = user_m.get_users()

output_file = args.output

写出json文件

print("--------result---------")

print(result)

configuration = json.loads(result)

写出yaml (dict)

with open(output_file, 'w') as yaml_file:

yaml.dump(configuration, yaml_file)

复制代码
print(result)

def get_user(args):

print('Provided command value is %r.' % args.command)

print('Provided input value is %r.' % args.input)

print('Provided output value is %r.' % args.output)

id = user_m.get_user_id(args.name)

result = user_m.get_user(id)

output_file = args.output

写出json文件

with open(output_file, 'w') as jsonfile:

json.dump(result, jsonfile, indent=4)

print(result)

if name == 'main ':

import sys

print(sys.argv)

parser = argparse.ArgumentParser()

define_args(parser)

parse_args(parser)

----------------------------------------------执行结果------------------------------------

root@controller python# python3 user_manager.py create --input '{ "name": "user01", "password": "000000", "description": "description" } '

{'auth': {'identity': {'methods': 'password', 'password': {'user': {'domain': {'name': 'demo'}, 'name': 'admin', 'password': '000000'}}}, 'scope': {'project': {'domain': {'name': 'demo'}, 'name': 'admin'}}}}

2022-10-11 17:39:22,843 获取Token值:gAAAAABjRTnKtdV9oDS_VfNDp8qtRC_sEElsQwJGqJTST8LHtqJUahTJtf8MVDa2Nplrjwo6_18D_Hm85j99D9G1TMq7jKEPqAynBx5nGkTXggQWJ-WJdPxad_e3qsrwfeL3JOqDK3RSHEkhZ1k1EQKWl3nxgMBhycHDs_3-CA4Cyfcmi9S15pQ

headers: {'X-Auth-Token': 'gAAAAABjRTnKtdV9oDS_VfNDp8qtRC_sEElsQwJGqJTST8LHtqJUahTJtf8MVDa2Nplrjwo6_18D_Hm85j99D9G1TMq7jKEPqAynBx5nGkTXggQWJ-WJdPxad_e3qsrwfeL3JOqDK3RSHEkhZ1k1EQKWl3nxgMBhycHDs_3-CA4Cyfcmi9S15pQ'}

-----------begin-----------------

'user_manager.py', 'create', '--input', '{ "name": "user01", "password": "000000", "description": "description" } '

create some thing

Provided command value is 'create'.

Provided input value is '{ "name": "user01", "password": "000000", "description": "description" } '.

Provided output value is None.

2022-10-11 17:39:23,137 返回状态:{"user": {"description": "description", "name": "user01", "domain_id": "default", "enabled": true, "links": {"self": "http://controller:5000/v3/users/01eebcdbcbf24bc4a5435f1dcd0949a7"}, "options": {}, "id": "01eebcdbcbf24bc4a5435f1dcd0949a7", "password_expires_at": null}}

--------write to json---------: {"user": {"description": "description", "name": "user01", "domain_id": "default", "enabled": true, "links": {"self": "http://controller:5000/v3/users/01eebcdbcbf24bc4a5435f1dcd0949a7"}, "options": {}, "id": "01eebcdbcbf24bc4a5435f1dcd0949a7", "password_expires_at": null}}

{"user": {"description": "description", "name": "user01", "domain_id": "default", "enabled": true, "links": {"self": "http://controller:5000/v3/users/01eebcdbcbf24bc4a5435f1dcd0949a7"}, "options": {}, "id": "01eebcdbcbf24bc4a5435f1dcd0949a7", "password_expires_at": null}}

相关推荐
雯宝11 小时前
mnt_init 函数
linux
律宏阔17 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔17 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴17 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千17 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei3717 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei3717 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei3717 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
GeW17 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux
GeW17 小时前
工业场景中的Linux与数据库选型:高端化转型的技术底座
linux