python¶
python 类型转换¶
int to binary
>>> bin(6) '0b110' >>> bin(6)[2:] '110'
binary to int
>>> int('11111111', 2) 255 >>> from bitstring import BitArray >>> b = Bitarray(bin='11111111') >>> b.uint 255 >>> b.int -1
import 问题¶
python 中 import 其它模块时,如果路径不对,会出现找不到模块的错误。 假设代码目录结构如下:
-- src |-- m1.py |-- mod2 | `-- m2.py |-- mod3 | `-- m3.py `-- main.py
主程序与模块在同一级目录
main.py
importm1.py
import m1
main.py
中 importm2.py
我们先试试直接 import, 则会报
ImportError: No module named ..
错误。>>> import mod2.m2 ImportError: No module named mod2.m2
这是因为 python 只会把有 __init__.py 文件的目录当做 python package. 在 mod2 目录下添加
__init__.py
文件, 此时目录结构如下:-- src |-- m1.py |-- mod2 | |-- __init__.py | `-- m2.py |-- mod3 | |-- __init__.py | `-- m3.py `-- main.py
此时再 import 就不会出错了。
>>> import mod2.m2
这里我们运行下面的代码看看:
>>> import mod2 >>> dir(mod2) ['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']
我们可以看到这里
dir
函数并没有打印 m2.py, 是不是感觉 比较奇怪,其实这里 import 只是导入了mod2.__init__.py
如果我们希望dir(mod2)
能看到 m2.py 里的函数,我们需要在 __init__.py 中 import m2m2
importm3
这种情况比较复杂, 如果程序的入口是
m2.py
, 那么导入方式如下:import sys sys.append('..') import m3
如果程序的入口是
main.py
然后在main.py
用到了m2, 那么导入方式如下:import mod1.m1
python json 处理¶
解析 json 数据¶
解析 json 分为两种,一种是解析 json 字符串, 另一种是解析 json 文件
解析 json 字符串
>>> import json >>> json_str = '{"name": "lina", "age": 23}' >>> json_obj = json.loads(json_str) >>> print json_obj {u'age': 23, u'name': u'lina'}
解析 json 文件
import json with open('json_file_path') as fp: json_obj = json.load(fp) # or use loads json_obj = json.loads(open('json_file_path').read())
转化为 json 字符串¶
转为为 json 字符串
import json json_obj = {u'age': 23, u'name': u'lina'} json_str = json.dumps(json_obj)
try 模块¶
python 中有一个 try..except..else 的组合。光看 try..except 跟其它语言查不多,可是为什么要加一个 else呢?
如果 except 没有捕获到异常,就会执行 else 部分的代码。既然不在 except 中执行,为什么不直接放到 try 语句中呢?这是因为如果我们 指定了 except 的类型,当出现其它 except 时,并不能捕获,所以就 走 else 流程了。需要注意的是,正常执行 try 语句之后也会执行 else 代码。
openstack¶
cloud-init 介绍¶
cloud-init 是一个系统配置工具,当系统起来时, cloud-init 会从固定分区读取数据,然后执行定制化 操作。
cloud-init 有四个执行阶段:
- local: cloud-init-local.service
- init: cloud-init.service
- config: cloud-config.service
- final: cloud-final.service
配置¶
cloud-init 各阶段完成哪些工作可以在 /etc/cloud/cloud.cfg
中查看
local 阶段
作为 cloud-init 的初始阶段,此时主要完成网口的配置
/usr/bin/cloud-init init --local
init 阶段
config 阶段
final 阶段
cloud-init 脚本生成¶
社区提供了 write-mime-multipart 工具来生成 cloud-init 脚本。 使用方法如下:
$ cat my-boothook.txt
#!/bin/sh
echo "Hello World!"
echo "This will run as soon as possible in the boot sequence"
$ cat my-user-script.txt
#!/usr/bin/perl
print "This is a user script (rc.local)\n"
$ cat my-include.txt
# these urls will be read pulled in if they were part of user-data
# comments are allowed. The format is one url per line
http://www.ubuntu.com/robots.txt
http://www.w3schools.com/html/lastpage.htm
$ cat my-upstart-job.txt
description "a test upstart job"
start on stopped rc RUNLEVEL=[2345]
console output
task
script
echo "====BEGIN======="
echo "HELLO From an Upstart Job"
echo "=====END========"
end script
$ cat my-cloudconfig.txt
#cloud-config
ssh_import_id: [smoser]
apt_sources:
- source: "ppa:smoser/ppa"
$ write-mime-multipart --output=combined-userdata.txt \
my-boothook.txt:text/cloud-boothook \
my-include.txt:text/x-include-url \
my-upstart-job.txt:text/upstart-job \
my-user-script.txt:text/x-shellscript \
my-cloudconfig.txt
User Data 输入格式¶
Gzip Compressed Content
Mime Multi Part archive
User-Data Script
以
#!
或Content-Type: text/x-shellscript
开头。存放用户脚本,可以是 python, shell, perl 等。
user data
里的脚本执行比较晚,类似 rc.local, 而且只在第一次启动时 执行。Include File
以
#include
或Content-Type: text/x-include-url
开头。includ file
的内容是一串 url, 每行一个,cloud-init 启动时会 读取 url 链接的内容。Cloud Config Data
以
#cloud-config
或Content-Type: text/cloud-config
开头, 内容按规定格式编写。Upstart Job
以
#upstart-job
或Content-Type: text/upstart-job
开头,文件内容会存放在 /etc/init ,以供其它 job 使用。
Cloud Boothook
以
#cloud-boothook
或Content-Type: text/cloud-boothook
开头。boothook
数据会保存到 /var/lib/cloud ,然后立刻执行。boothook
每次上电都会执行,没有机制指定只运行一次。Part Handler
BFV¶
ipxe 介绍¶
ipxe 是 pxe 的扩展,提供了如下功能:
- boot from a web server via HTTP
- boot from an iSCSI SAN
- boot from a Fibre Channel SAN via FCoE
- boot from an AoE SAN
- boot from a wireless network
- boot from a wide-area network
- boot from an Infiniband network
- control the boot process with a script
ipxe 使用¶
使用 ipxe 有两种方式:
- 使用 ipxe 固件替换网卡的 PXE ROM
- 使用链式启动来加载 ipxe 固件
ipxe 可以从: http://boot.ipxe.org/ipxe.iso 下载, 但是要想使用 ipxe 的全部功能,建议通过源码自己编译。 编译方法如下:
git clone git://git.ipxe.org/ipxe.git
cd ipxe/src
make
编译¶
编译成 iso
make bin/ipxe.iso
编译成 usb
make bin/ipxe.usb dd if=bin/ipxe.usb of=/dev/sdX
编译成 pxe rom 的链式加载文件
make bin/undionly.kpxe
替代现有 PXE ROM
make bin/808610de.rom
ironic 使用 ipxe¶
创建 http 根目录
mkdir -p /tftpboot mkdir -p /httpboot chown -R ironic /tftpboot chown -R ironic /httpboot
设置 tftp map file
echo 'r ^([^/]) /tftpboot/\1' > /tftpboot/map-file echo 'r ^(/tftpboot/) /tftpboot/\2' >> /tftpboot/map-file
配置 tftp 和 http server
[pxe] tftp_root=/tftpboot tftp_server=192.168.0.2 ipxe_enabled=True [deploy] http_root=/httpboot http_url=http://192.168.0.2:8080
配置 http 服务器
这里以 apacha 为例,如果使用 nginx 请参考 nginx 的配置方法。
- 安装 httpd
$ sudo yum install httpd
- 配置 httpd
修改
/etc/httpd/conf/httpd.conf
<Directory /> Options Indexes FollowSymLinks AllowOverride none </Directory> DocumentRoot "/httpboot"
- 重启服务
$ sudo systemctl restart httpd
设置 ipxe 模板
[pxe] pxe_bootfile_name=undionly.kpxe pxe_config_template = $pybasedir/drivers/modules/ipxe_config.template
安装 iPXE 相关包
yum install ipxe-bootimgs cp /usr/share/ipxe/{undionly.kpxe,ipxe.efi} /tftpboot
重启 conductor 服务
sudo systemctl restart openstack-ironic-conductor
rabbitmq¶
介绍¶
rabbitmq 是消息处理的中间人,可以类比现实生活中的邮局。
术语¶
生产者
发送消息的程序叫生产者。
消费者
接收消息的程序称为消费者。
消息队列
消息队列驻留在 rabbitmq 中,用来存放消息,理论上消息队列大小 无限制,实际上跟机器的内存和硬盘大小有关。
生产者消费者模型¶
大部分情况下生成者,消费者,消息队列都在不同的机器上。我们先看一个
hello world
的例子。
模型如下图:

生产者代码:
#!/usr/bin/env python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
channel.basic_publish(exchange='',
routing_key='hello',
body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()
消费者代码:
#!/usr/bin/env python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(callback,
queue='hello',
no_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
RPC 模型¶
call 方法¶
cctxt = self.client.prepare(topic=topic or self.topic, version='1.22')
cctxt.call(context, 'do_node_deploy', node_id=node_id,
rebuild=rebuild, configdrive=configdrive)
cast 方法¶
OS¶
SUSE¶
源配置¶
使用 yast 进入图形化配置,然后添加如下源
- 163/Update; URL: http://mirrors.163.com/openSUSE/update/13.2/
- 163/Oss; URL: http://mirrors.163.com/openSUSE/distribution/13.2/repo/oss/
- 163/NON-Oss; URL: http://mirrors.163.com/openSUSE/distribution/13.2/repo/non-oss/
SQL¶
常用sql¶
逻辑运算¶
sql 中用 OR 和 AND 来表示条件的 或 和 且
$ SELECT * FROM World;
+-----------------+------------+------------+--------------+---------------+
| name | continent | area | population | gdp |
+-----------------+------------+------------+--------------+---------------+
| Afghanistan | Asia | 652230 | 25500100 | 20343000 |
| Albania | Europe | 28748 | 2831741 | 12960000 |
| Algeria | Africa | 2381741 | 37100000 | 188681000 |
| Andorra | Europe | 468 | 78115 | 3712000 |
| Angola | Africa | 1246700 | 20609294 | 100990000 |
+-----------------+------------+------------+--------------+---------------+
$ SELECT name,population,area FROM World WHERE area > 3000000 OR population > 25000000;
+--------------+-------------+--------------+
| name | population | area |
+--------------+-------------+--------------+
| Afghanistan | 25500100 | 652230 |
| Algeria | 37100000 | 2381741 |
+--------------+-------------+--------------+
分组统计¶
$ SELECT * FROM Person;
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
$ SELECT Email FROM Person GROUP BY Email having count(Email) > 1;
+---------+
| Email |
+---------+
| a@b.com |
+---------+