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

相关推荐
Mr'liu30 分钟前
MongoDB 7.0 副本集高可用部署
linux·mongodb
文静小土豆1 小时前
Rocky Linux 二进制 安装K8S-1.35.0高可用集群
linux·运维·kubernetes
暮云星影1 小时前
二、linux系统 应用开发:整体Pipeline流程
linux·arm开发
weixin_430750933 小时前
OpenMediaVault debian Linux安装配置企业私有网盘(三) 静态ip地址配置
linux·服务器·debian·nas·网络存储系统
403240733 小时前
[Jetson/Ubuntu 22.04] 解决挂载 exFAT 硬盘报错 “unknown filesystem type“ 及只读权限问题的终极指南
linux·运维·ubuntu
Source.Liu3 小时前
【沟通协作软件】使用 Rufus 制作 Ubuntu 启动盘的详细过程
linux·ubuntu
Love丶伊卡洛斯3 小时前
Ubuntu 部署 STUN服务端
linux·运维·ubuntu
梁洪飞3 小时前
通过链接文件和Start.S学习armv7
linux·arm开发·嵌入式硬件·学习·arm
DN金猿4 小时前
使用ubuntu安装nginx时报错
linux·nginx·ubuntu
小赵还有头发4 小时前
安装Ceres与glog
linux·学习·无人机·ceres·glog