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}}

相关推荐
孤寂大仙v1 小时前
【Linux笔记】——Linux线程封装
linux·笔记·算法
樂5022 小时前
RHCE 练习三:架设一台 NFS 服务器
linux·服务器·网络
小飞敲代码2 小时前
【Hadoop 实战】Yarn 模式上传 HDFS 卡顿时 “No Route to Host“ 错误深度解析与解决方案
大数据·linux·运维·服务器·hadoop·分布式·hdfs
zanglengyu2 小时前
RK3568解码1080P视频时遇到系统崩溃内核挂掉的解决方案
linux·音视频·rockchip
遇见火星2 小时前
在CentOS系统上部署GitLabRunner并配置CICD自动项目集成!
linux·运维·ci/cd·centos·gitlabrunner
我不是程序猿儿4 小时前
【C#】用 DevExpress 创建带“下拉子表”的参数表格视图
linux·windows·c#
咖喱年糕4 小时前
【Linux】系统指令与开发全栈(vim、ssh、gcc)
linux·ssh·vim·gcc
charlie1145141916 小时前
Linux内核深入学习(4)——内核常见的数据结构2——红黑树
linux·数据结构·学习·红黑树
chen.@-@6 小时前
Linux 常用命令
linux
不愧是你呀7 小时前
Linux利用多线程和线程同步实现一个简单的聊天服务器
linux·服务器