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)).textprint(f"创建镜像的信息为:{req}")return reqdef 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 reqdef get_image(self,id):url = self.resUrl + "/" + idreq = json.loads(requests.get(self.resUrl,headers=self.headers).text)print(f"获取到的镜像信息为:{req}")return reqdef delete_image(self,id):url = self.resUrl + "/" + idreq = 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 = connectdef list_servers(self):"""查询所有云主机."""#to jsonitems = 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 = connectdef list_images(self):"""查询所有镜像"""#to jsonitems = self.connect.compute.images()images_jsons = {}for image in items:images_jsons[image['name']] = imagereturn json.dumps(images_jsons,indent=2)def get_image(self, image_name:str):"""查询镜像"""#to jsonimage = self.connect.compute.find_image(image_name)return json.dumps(image,indent=2)

class flavor_manager:

def __init__(self, connect):self.connect = connectdef list_flavors(self):"""查询所有云主机类型"""#to jsonitems = self.connect.compute.flavors()flavors_jsons = {}for flavor in items:flavors_jsons[flavor['name']] = flavorreturn json.dumps(flavors_jsons,indent=2)def get_flavor(self, flavor_name:str):"""根据名称获取云主机类."""#to jsonflavor = self.connect.compute.find_flavor(flavor_name)return json.dumps(flavor,indent=2)

class network_manager:

def __init__(self, connect):self.connect = connectdef list_networks(self):"""查询所有网络."""#to jsonitems = self.connect.network.networks()items_jsons = {}for network in items:items_jsons[network['name']] = networkreturn json.dumps(items_jsons,indent=2)def get_network(self, network_name:str):"""跟名称查询网络."""#to jsonflavor = 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=handersself.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).textlogger.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_iddef get_flavor(self, id:str):api_url = self.resUrl + "/"+idresult = json.loads(requests.get(api_url, headers=self.headers).text)logger.debug(f"返回信息:{str(result)}")return resultdef delete_flavor(self, id:str):api_url = self.resUrl + "/"+idresponse = requests.delete(api_url, headers=self.headers)#Normal response codes: 202 without return textif 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 + "/" + idresponse = requests.put(api_url, data=json.dumps(body), headers=self.headers)# Normal response codes: 202 without return textif 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).textlogger.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).textlogger.debug(f"返回状态:{str(status_code)}")return status_codedef 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_namefor 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 + "/" + idresult = json.loads(requests.get(api_url, headers=self.headers).text)logger.debug(f"返回信息:{str(result)}")return resultdef delete_user(self, name: str):"""delete a user by id."""id = self.get_user_id(name)api_url = self.resUrl + "/" + idresponse = 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 textif 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}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/159624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】贝叶斯分类器

贝叶斯分类器是一种概率模型,利用贝叶斯公式来解决分类问题。假设样本的特征向量服从一定的概率分布,我们就可以计算出该特征向量属于各个类的条件概率。分类结果是条件概率最大的分类结果。如果假设特征向量的每个分量彼此独立,则它是朴素贝…

Java,数据结构与集合源码,关于List接口的实现类(ArrayList、Vector、LinkedList)的源码剖析

目录 ArrayList ArrayList的特点: ArrayList源码解析: Vector Vector的特点: Vector源码解析: LinkedList LinkedList的特点: LinkedList的源码剖析: 使用说明: ArrayList ArrayList的…

开源和闭源软件对开发的影响

开源软件的优势: 开源性:开源软件允许任何人查看、修改和发布源代码,这促进了代码的共享和集体学习。透明性:开源软件提高了软件的透明度,使用户可以更好地理解软件的工作原理,增加对软件的信任。社区支持…

【OpenCV实现图像:OpenCV利用Python创作热力图】

文章目录 概要读取图像图像灰度化**像素化效果**小结 概要 热力图是一种强大的统计图表,通过对数据进行色彩映射,直观展示了数据分布的热度和密度。在绘制热力图时,关键在于指定颜色映射的规则,这决定了图中不同数值的呈现方式。…

matlab 一些画图法总结(持续更新)

*****************************************画Dmd_L极坐标表示法**************************************** if(~exist(Dmd_L_array)) Dmd_L_array []; end Dmd_L_array [Dmd_L_array; Dmd_L]; thetaangle(Dmd_L_array); rabs(Dmd_L_array); polarplot(theta,r,o); *****…

【教程】ACM 模式输入输出 C++

目录 输入输出输入单个数字 or 字符输入单行数列输入单行字符串输入多行符号列&#xff0c;已知行数和列数 字符串处理删除字符串中的某个字符 / 子串find()erase() 输入字符串并分割到 vector\<string> 中getline()stringstream示例 快速排序其他 输入输出 输入单个数字…

渗透实例------2个星期艰难的渗透纪实

2个星期艰难的渗透纪实 kyo327 入侵原因,需删一帖子,目标用www.111.com代替,前期通过初期的网站文件暴力猜解,扫描到robots.txt这个文件,有以下目录。如图1: 图1 再通过对这些文件的访问,从3gadm.php文件的标题栏得到该网站采用的是diy-page8.3的cms,自然可以先用搜索…

导购APP、淘客查券机器人与淘客系统:全面对比与选择

导购APP、淘客机器人与淘客系统&#xff1a;全面对比与选择 在互联网购物的时代&#xff0c;导购APP、淘客机器人和微赚淘客系统成为了消费者们的三大重要工具。它们各具优势&#xff0c;但也存在一些问题。本文将为您详细对比这三种工具&#xff0c;帮助您在购物时做出最合适…

Android JNI 异常定位(2)—— addr2line

Android native报错有时候只有一句 signal 11 (SIGSEGV)&#xff0c;这种情况仅通过log是很难定位到问题的。不过Android 在/data/tombstones目录保存了错误的堆栈信息&#xff0c;为定位bug提供了路径。不过一般这里的log都无法像java一样直接定位的出错的行数。如下图&#x…

2023做车载测试真的可以远离内耗!转行车载月入20K!

2023年&#xff0c;车载测试正处于一个发展阶段&#xff0c;随着新能源汽车的蓬勃发展&#xff0c;电气化、智能化逐渐成为发展趋势。在汽车开发过程中&#xff0c;测试是非常重要的一个环节。现在软件越来越多地被应用到汽车上&#xff0c;对软件测试的需求也越来越多、越来越…

Linux上使用ldapsearch命令通过AD GC查询指定用户

一&#xff0c;前言 需要你对Microsoft AD ,AD GC有一定的了解&#xff0c;并且AD要启用了GC。特别是要弄懂&#xff0c;林和域的关系,你才能明白GC在他俩之间的关系。 GC中文名&#xff1a;全局编录 会将你林下所有域的所有对象存储在一个目录里面&#xff0c;但是并没有存储…

数据库数据恢复—MongoDB数据库文件拷贝出现错误的数据恢复案例

MongoDB数据库数据恢复环境&#xff1a; 一台Windows Server操作系统的虚拟机&#xff0c;虚拟机上部署有MongoDB数据库。 MongoDB数据库故障&检测&#xff1a; 在未关闭MongoDB服务的情况下&#xff0c;工作人员将MongoDB数据库文件拷贝到其他分区&#xff0c;然后将原数…

力扣:175. 组合两个表(Python3)

题目&#xff1a; 表: Person ---------------------- | 列名 | 类型 | ---------------------- | PersonId | int | | FirstName | varchar | | LastName | varchar | ---------------------- personId 是该表的主键&#xff08;具有唯一值的列&#…

js进阶笔记之原型,原型链

目录 1、原型对象 constructor 属性 对象原型 2、原型链 3、instanceof 4、原型继承 1、原型对象 面向过程就是分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步实现&#xff0c;使用的时候再一个一个的依次调用就可以了。 面向对象是把事务分解成为…

音频采集的相关基础知识

本文引注: https://zhuanlan.zhihu.com/p/652629744 1.麦克风的种类 (1)模拟麦克风 ECM麦克风&#xff1a;驻极体电容麦克风(ECM)&#xff0c;典型的汽车ECM麦克风是一种将ECM单元与小型放大器电路整合在单个外壳中的装置。放大器提供一个模拟信号&#xff0c;其电压电平允许…

软件工程理论与实践 (吕云翔) 第十一章: 软件编程课后习题及其答案解析

第十一章&#xff1a; 软件编程 1.判断题 &#xff08;1&#xff09;C语言是一种纯面向对象语言。&#xff08;&#xff09; &#xff08;2&#xff09;进行程序设计语言的选择时&#xff0c;首先考虑的是应用领域。&#xff08;√&#xff09; &#xff08;3&#xff09;良…

JavaScript 如何拷贝对像(Object)或者数组(Array)

目录 JavaScript数据拷贝类型 浅拷贝 深拷贝 举例&#xff1a; 浅拷贝 数组 对象 深拷贝 lodash cloneDeep使用示例 自定义深拷贝方法示例 JSON.parse() 和 JSON.stringify()使用示例 JavaScript数据拷贝类型 浅拷贝 数组可以使用Array.prototype.slice()方法 …

JS实现数字千分位分割(手写纯享版)

简介 在前端开发中&#xff0c;我们经常需要对数字进行格式化&#xff0c;其中一种常见的需求就是将数字表示为千分位格式&#xff0c;以提高可读性。本文将介绍如何使用 JavaScript 实现一个简单而有效的千分位格式化函数。 千分位格式化的需求 千分位格式化是一种将数字中…

python实现鼠标实时坐标监测

python实现鼠标实时坐标监测 一、说明 使用了以下技术和库&#xff1a; tkinter&#xff1a;用于创建GUI界面。pyperclip&#xff1a;用于复制文本到剪贴板。pynput.mouse&#xff1a;用于监听鼠标事件&#xff0c;包括移动和点击。threading&#xff1a;用于创建多线程&…

PWM实验

PWM相关概念 PWM:脉冲宽度调制定时器 脉冲&#xff1a;方波信号&#xff0c;高低电平变化产生方波 周期&#xff1a;高低电平变化所需要时间 频率&#xff1a;1s钟可以产生方波个数 占空比&#xff1a;在一个方波内&#xff0c;高电平占用的百分比 宽度调制&#xff1a;占…