OpenStack针对不同的用户提供4种与Python API交互的方式:
1)OpenStack SDK
2)Shadow
3)per-project libraries
4)直接通过RESTful调用keystoneauth
前提知识:
1)RESTful Web 服务
2)HTTP /1.1
3)JSON与数据序列化格式
1.OpenStack SDK
OpenStack Software Development Kit(OpenStack SDK),用于编写创建Python的自动化脚本,并在openstack中管理云资源。SDK实现了与OpenStack API 的Python绑定,使你能够通过调用Python对象来执行Python中的自动化任务,而不是直接使用REST调用。
新用户应该使用OpenStack SDK 来进行编码。
2.Shadow
Shadow是一个抽象库(就是没有实现的),专注于隐藏OpenStack云之间的实现差异。虽然OpenStack SDK向底层REST API提供了一个干净的对象接口,但如果这样做有利的话,阴影隐藏它们。如果您计划针对许多OpenStack云运行相同的Python程序,则可能需要使用阴影 - 但是如果您需要访问没有云中性抽象映射的云的任何功能,则无法执行此操作有阴影。
3.per-project libraries
每个OpenStack项目都会生成一个包装自己的REST API的客户端库。除非因某些原因没有其他选择,否则应避免每个项目库。
4.直接通过REST调用keystoneauth
所有OpenStack的API实际上都是REST API。
该 keystoneauth库提供了一个对象,它看起来非常像一个 会话从Python对象 请求库,处理所有身份验证的为您服务。
如果您更轻松地处理REST,或者如果您的云中实现了某项功能,但尚未在任何library中获得支持,则此选项适用于你。
安装OpenStack SDK
每个OpenStack项目都有自己的python库。
这些库命令与命令行客户机捆绑在一起。例如:compute API 的Python绑定与python-novaclient包捆绑在一起。
注意:项目的理解:
keystone 是一个项目 neutron是一个项目 nova使用一个项目 等等
keystone是你注册project
认证(Authenticate )
使用SDK时候,你必须先对OpenStack 的endpoint进行身份验证,然后才能使用OpenStack 服务。因为所有项目都使用keystone进行身份验证,所以无论你决定更使用哪种服务或者库,这个过程都是一样的。每个library都有更加先进和复杂的方式来做事情,如果有需要的话。
处理云配置和凭据有两种基本方法:
1)环境变量通过openrc.sh文件
2)clouds.yaml配置文件
环境变量已经是使用最久的,是您最有可能从云提供商那里获得的形式。如果您只有一个云端帐户,那么它们是最方便的方式。
clouds.yaml
是一个新的方式,旨在帮助有多个OpenStack云使用他们的人。
openrc.sh:里面存放的是环境变量。比如账号,密码等。
创建一个经典客户端对象
所有的传统客户端对象可以以相同的方式构造-唯一的区别是第一个参数make_client
不同。
下面的例子可以使用compute 去获得一个nova client,但是neutron能够通过将compute
改为network
获得。
要使用具有Compute endpoint 的 python-novaclient,请使用下面的方法创建:
import os_client_config
nova = os_client_config.make_client(
'compute',
auth_url='https://example.com',
username='example-openstack-user',
password='example-password',
project_name='example-project-name',
region_name='example-region-name')
如果你想要一个特定的微型版本的Nova API,你可以把它作为version参数:
import os_client_config
nova = os_client_config.make_client(
'compute',
version='2.10',
auth_url='https://example.com',
username='example-openstack-user',
password='example-password',
project_name='example-project-name',
region_name='example-region-name')
注意:nova client代表的是可以操作nova的相关功能。
如果对使用自定义身份验证endpoint进行身份验证,则必须在auth_type参数中提供插件的名称 。
例如,Rackspace公共云是具有可选的自定义身份验证后端的OpenStack部署。正常的梯形密码认证工作原理非常好,你可能希望使用rackspace-keystonauth-plugin
中定制的rackspace keystoneauth API Key 插件。
nova = os_client_config.make_client(
'compute',
auth_type='rackspace_apikey',
auth_url='https://example.com',
username='example-openstack-user',
api_key='example-apikey',
project_name='example-project-name',
region_name='example-region-name')
管理image
在使用SDK中的image的时候,你将调用glance
和nova
。
列出image:
import glanceclient.v2.client as glclient
glance = glclient.Client(...)
images = glance.images.list()
images方法返回一个python生成器(generator),如以下雨python解释器的交互所示:
>>> images = glance.images.list()
>>> images
>>> list(images)
[{u'checksum': u'f8a2eeee2dc65b3d9b6e63678955bd83',
u'container_format': u'ami',
u'created_at': u'2013-10-20T14:28:10Z',
u'disk_format': u'ami',
u'file': u'/v2/images/dbc9b2db-51d7-403d-b680-3f576380b00c/file',
u'id': u'dbc9b2db-51d7-403d-b680-3f576380b00c',
u'kernel_id': u'c002c82e-2cfa-4952-8461-2095b69c18a6',
u'min_disk': 0,
u'min_ram': 0,
u'name': u'cirros-0.3.5-x86_64-uec',
u'protected': False,
u'ramdisk_id': u'4c1c9b4f-3fe9-425a-a1ec-1d8fd90b4db3',
u'schema': u'/v2/schemas/image',
u'size': 25165824,
u'status': u'active',
u'tags': [],
u'updated_at': u'2013-10-20T14:28:11Z',
u'visibility': u'public'},
{u'checksum': u'69c33642f44ca552ba4bb8b66ad97e85',
u'container_format': u'ari',
u'created_at': u'2013-10-20T14:28:09Z',
u'disk_format': u'ari',
u'file': u'/v2/images/4c1c9b4f-3fe9-425a-a1ec-1d8fd90b4db3/file',
u'id': u'4c1c9b4f-3fe9-425a-a1ec-1d8fd90b4db3',
u'min_disk': 0,
u'min_ram': 0,
u'name': u'cirros-0.3.5-x86_64-uec-ramdisk',
u'protected': False,
u'schema': u'/v2/schemas/image',
u'size': 3714968,
u'status': u'active',
u'tags': [],
u'updated_at': u'2013-10-20T14:28:10Z',
u'visibility': u'public'},
{u'checksum': u'c352f4e7121c6eae958bc1570324f17e',
u'container_format': u'aki',
u'created_at': u'2013-10-20T14:28:08Z',
u'disk_format': u'aki',
u'file': u'/v2/images/c002c82e-2cfa-4952-8461-2095b69c18a6/file',
u'id': u'c002c82e-2cfa-4952-8461-2095b69c18a6',
u'min_disk': 0,
u'min_ram': 0,
u'name': u'cirros-0.3.5-x86_64-uec-kernel',
u'protected': False,
u'schema': u'/v2/schemas/image',
u'size': 4955792,
u'status': u'active',
u'tags': [],
u'updated_at': u'2013-10-20T14:28:09Z',
u'visibility': u'public'}]
通过ID获得image
要从ID中检索出图像对象,请调用以下方法:
import glanceclient.v2.client as glclient
image_id = 'c002c82e-2cfa-4952-8461-2095b69c18a6'
glance = glclient.Client(...)
image = glance.images.get(image_id)
通过名字获得image:
image服务python绑定 不支持按名称检索image对象。然而,compute python 绑定(nova),可以让你通过名称获得Image对象。用通过名称获取Image对象,方法如下:
import novaclient.v2.client as nvclient
name = "cirros"
nova = nvclient.Client(...)
image = nova.images.find(name=name)
上传镜像:
import glanceclient.v2.client as glclient
imagefile = "/tmp/myimage.img"
glance = glclient.Client(...)
with open(imagefile) as fimage:
glance.images.create(name="myimage", is_public=False, disk_format="qcow2",
container_format="bare", data=fimage)
将CORS header 分配给请求
跨原始资源共享 Cross-Origin Resource Sharing(CORS)
是一个贵方,用于定义浏览器和服务器如果通过使用HTTP headers(标头),例如由Object Storage API 请求分配的HTTP 头 进行通信。对象存储API支持以下headers:
调用对象为了删除:
要确定对象存储系统是否支持此功能,请参阅管理对象和容器。
计划要删除的对象有助于管理不想永久存储的对象,例如日志文件,数据集的定期备份,或者在指定时间过时的文档或者图像。
要安排一个要删除的对象,请在对象中包含这些头中的一个PUT或者POST 请求:
X-Delete-At
UNIX纪元的事件戳,是证书形式。例如:1348691905
(时间戳)代表的是:Wed, 26 Sept 2012 20:38:25 GMT
。
它指定您希望对象到期的时间,不再被提供,并从对象存储完全删除。
X-Delete-After
就是请求之后,隔了这么多时间就删除。
注意:X-Delete-At
和X-Delete-After
都是请求头里面的参数。
使用POST
方法将过期标头分配给要过期的现有对象。
下面的例子是执行之后在时间戳1390581073
失效:
$ curl -i publicURL/marktwain/goodbye -X PUT -H "X-Auth-Token: token" \
-H "X-Delete-At: 1390581073" -H "Content-Length: 14" -H \
"Content-Type: application/octet-stream"
下面是经过864000
久之后失效:
PUT ////
配置实例的访问和安全性
当使用SDK中的图像时,你将调用novaclient
方法。
添加密钥对:
生成一个密钥对,可以调用:novaclient.v1_1.keypairs.KeypairManager.create
方法:
import novaclient.v2.client as nvclient
nova = nvclient.Client(...)
keypair_name = "staging"
keypair = nova.keypairs.create(name=keypair_name)
print keypair.private_key
python脚本输出会是这样的:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA8XkaMqInSPfy0hMfWO+OZRtIgrQAbQkNcaNHmv2GN2G6xZlb\nuBRux5Xk/6SZ
ABaNPm1nRWm/ZDHnxCsFTcAl2LYOQXx3Cl2qKNY4r2di4G48GAkd\n7k5lDP2RgQatUM8npO0CD9PU
...
mmrceYYK08/lQ7JKLmVkdzdQKt77+v1oBBuHiykLfI6h1m77NRDw9r8cV\nzczYeoALifpjTPMkKS8
ECfDCuDn/vc9K1He8CRaJHf8AMLQLM3MN
-----END RSA PRIVATE KEY-----
你通常将私钥写入文件以便稍后使用。该文件只能由文件所有者读取和写入;否则,SSH客户端将拒绝读取私钥文件。最安全的方法是使用适当的权限创建文件:
import novaclient.v2.client as nvclient
import os
nova = nvclient.Client(...)
keypair_name = "staging"
private_key_filename = "/home/alice/id-staging"
keypair = nova.keypairs.create(name=keypair_name)
# Create a file for writing that can only be read and written by
owner
fp = os.open(private_key_filename, os.O_WRONLY | os.O_CREAT, 0o600)
with os.fdopen(fp, 'w') as f:
f.write(keypair.private_key)
导入密钥对:
如果已经使用位于该公钥的密钥对生成了密钥对,则~/.ssh/id_rsa.pub
将该文件的内容传递给novaclient.v1_1.keypairs.KeypairManager.create
方法将公钥导入到Compute:
import novaclient.v2.client as nvclient
import os.path
with open(os.path.expanduser('~/.ssh/id_rsa.pub')) as f:
public_key = f.read()
nova = nvclient.Client(...)
nova.keypairs.create('mykey', public_key)
列出密钥对:
import novaclient.v2.client as nvclient
nova = nvclient.Client(...)
keypairs = nova.keypairs.list()
创建和管理安全组:
import novaclient.v2.client as nvclient
nova = nvclient.Client(...)
security_groups = nova.security_groups.list()
创建具有指定名称和描述的安全组:
import novaclient.v2.client as nvclient
nova = nvclient.Client(...)
nova.security_groups.create(name="web", description="Web servers")
删除安全组:
import novaclient.v2.client as nvclient
nova = nvclient.Client(...)
group = nova.security_groups.find(name="web")
nova.security_groups.delete(group)
# The following lines would also delete the group:
# nova.security_groups.delete(group.id)
# group.delete()
创建和管理安全组角色:
查看安全组角色:
import novaclient.v2.client as nvclient
nova = nvclient.Client(...)
group = nova.security_groups.find(name="web")
print group.rules
增加角色给安全组:
import novaclient.v2.client as nvclient
nova = nvclient.Client(...)
group = nova.security_groups.find(name="web")
# Add rules for ICMP, tcp/80 and tcp/443
nova.security_group_rules.create(group.id, ip_protocol="icmp",
from_port=-1, to_port=-1)
nova.security_group_rules.create(group.id, ip_protocol="tcp",
from_port=80, to_port=80)
nova.security_group_rules.create(group.id, ip_protocol="tcp",
from_port=443, to_port=443)
网络
要理解用本节的信息,应该对OpenStack Networking,OpenStack Compute以及两者之间的集成有一个一般的了解。还应该可以访问实现Networking API v2.0的插件。
设置环境变量:
确保你设置相关的环境变量。
使用shell 文件设置以下的环境变量去获得凭证:
export OS_USERNAME="admin"
export OS_PASSWORD="password"
export OS_TENANT_NAME="admin"
export OS_AUTH_URL="http://IPADDRESS/v2.0"
获取凭证,本节中的示例使用以下的方法:
def get_credentials():
d = {}
d['username'] = os.environ['OS_USERNAME']
d['password'] = os.environ['OS_PASSWORD']
d['auth_url'] = os.environ['OS_AUTH_URL']
d['tenant_name'] = os.environ['OS_TENANT_NAME']
return d
就是一个字典,里面包含了环境信息。
上面的代码存在于credentials.py
,都是被导入进来了的,
所以可以简单使用下面的方法获得字典:
nova_credentials = get_nova_credentials()
打印值:
def print_values(val, type):
if type == 'ports':
val_list = val['ports']
if type == 'networks':
val_list = val['networks']
if type == 'routers':
val_list = val['routers']
for p in val_list:
for k, v in p.items():
print("%s : %s" % (k, v))
print('\n')
def print_values_server(val, server_id, type):
if type == 'ports':
val_list = val['ports']
if type == 'networks':
val_list = val['networks']
for p in val_list:
bool = False
for k, v in p.items():
if k == 'device_id' and v == server_id:
bool = True
if bool:
for k, v in p.items():
print("%s : %s" % (k, v))
print('\n')
上面的代码是存在于utils.py
文件中,可以直接导入。
创建网络:
#!/usr/bin/env python
from neutronclient.v2_0 import client
from credentials import get_credentials
network_name = 'sample_network'
credentials = get_credentials()
neutron = client.Client(**credentials)
try:
body_sample = {'network': {'name': network_name,
'admin_state_up': True}}
netw = neutron.create_network(body=body_sample)
net_dict = netw['network']
network_id = net_dict['id']
print('Network %s created' % network_id)
body_create_subnet = {'subnets': [{'cidr': '192.168.199.0/24',
'ip_version': 4, 'network_id': network_id}]}
subnet = neutron.create_subnet(body=body_create_subnet)
print('Created subnet %s' % subnet)
finally:
print("Execution completed")
列出网络:
#!/usr/bin/env python
from neutronclient.v2_0 import client
from credentials import get_credentials
from utils import print_values
credentials = get_credentials()
neutron = client.Client(**credentials)
netw = neutron.list_networks()
print_values(netw, 'networks')
创建端口:
#!/usr/bin/env python
from neutronclient.v2_0 import client
import novaclient.v2.client as nvclient
from credentials import get_credentials
from credentials import get_nova_credentials
credentials = get_nova_credentials()
nova_client = nvclient.Client(**credentials)
# Replace with server_id and network_id from your environment
server_id = '9a52795a-a70d-49a8-a5d0-5b38d78bd12d'
network_id = 'ce5d204a-93f5-43ef-bd89-3ab99ad09a9a'
server_detail = nova_client.servers.get(server_id)
print(server_detail.id)
if server_detail != None:
credentials = get_credentials()
neutron = client.Client(**credentials)
body_value = {
"port": {
"admin_state_up": True,
"device_id": server_id,
"name": "port1",
"network_id": network_id
}
}
response = neutron.create_port(body=body_value)
print(response)
监听端口:
#!/usr/bin/env python
from neutronclient.v2_0 import client
from credentials import get_credentials
from utils import print_values
credentials = get_credentials()
neutron = client.Client(**credentials)
ports = neutron.list_ports()
print_values(ports, 'ports')
监听服务端口:
#!/usr/bin/env python
from neutronclient.v2_0 import client
import novaclient.v2.client as nvclient
from credentials import get_credentials
from credentials import get_nova_credentials
from utils import print_values_server
credentials = get_nova_credentials()
nova_client = nvclient.Client(**credentials)
# change these values according to your environment
server_id = '9a52795a-a70d-49a8-a5d0-5b38d78bd12d'
network_id = 'ce5d204a-93f5-43ef-bd89-3ab99ad09a9a'
server_detail = nova_client.servers.get(server_id)
print(server_detail.id)
if server_detail is not None:
credentials = get_credentials()
neutron = client.Client(**credentials)
ports = neutron.list_ports()
print_values_server(ports, server_id, 'ports')
body_value = {'port': {
'admin_state_up': True,
'device_id': server_id,
'name': 'port1',
'network_id': network_id,
}}
response = neutron.create_port(body=body_value)
print(response)
创建路由和给子网增加端口:
1)导入modules:
from neutronclient.v2_0 import client
import novaclient.v2.client as nvclient
from credentials import get_credentials
from credentials import get_nova_credentials
from utils import print_values_server
2)获得nova凭证,可以参考上面的。
3)创建nova_client
实例:
nova_client = nvclient.Client(**credentials)
4)为子网创建路由和端口:
# Replace with network_id from your environment
network_id = '81bf592a-9e3f-4f84-a839-ae87df188dc1'
credentials = get_credentials()
neutron = client.Client(**credentials)
neutron.format = json
request = {'router': {'name': 'router name',
'admin_state_up': True}}
router = neutron.create_router(request)
router_id = router['router']['id']
# for example: '72cf1682-60a8-4890-b0ed-6bad7d9f5466'
router = neutron.show_router(router_id)
print(router)
body_value = {'port': {
'admin_state_up': True,
'device_id': router_id,
'name': 'port1',
'network_id': network_id,
}}
response = neutron.create_port(body=body_value)
print(response)
print("Execution Completed")
创建路由:完整示例 :
#!/usr/bin/env python
from neutronclient.v2_0 import client
import novaclient.v2.client as nvclient
from credentials import get_credentials
from credentials import get_nova_credentials
from utils import print_values_server
credentials = get_nova_credentials()
nova_client = nvclient.Client(**credentials)
# Replace with network_id from your environment
network_id = '81bf592a-9e3f-4f84-a839-ae87df188dc1'
try:
credentials = get_credentials()
neutron = client.Client(**credentials)
neutron.format = 'json'
request = {'router': {'name': 'router name',
'admin_state_up': True}}
router = neutron.create_router(request)
router_id = router['router']['id']
# for example: '72cf1682-60a8-4890-b0ed-6bad7d9f5466'
router = neutron.show_router(router_id)
print(router)
body_value = {'port': {
'admin_state_up': True,
'device_id': router_id,
'name': 'port1',
'network_id': network_id,
}}
response = neutron.create_port(body=body_value)
print(response)
finally:
print("Execution completed")
删除网络:
1)导入模块:
from neutronclient.v2_0 import client
from credentials import get_credentials
2)获得凭证:Get Nova credentials.
3)创建实例:
neutron = client.Client(**credentials)
4)删除网络:
body_sample = {'network': {'name': network_name,
'admin_state_up': True}}
netw = neutron.create_network(body=body_sample)
net_dict = netw['network']
network_id = net_dict['id']
print('Network %s created' % network_id)
body_create_subnet = {'subnets': [{'cidr': '192.168.199.0/24',
'ip_version': 4, 'network_id': network_id}]}
subnet = neutron.create_subnet(body=body_create_subnet)
print('Created subnet %s' % subnet)
neutron.delete_network(network_id)
print('Deleted Network %s' % network_id)
print("Execution completed")
完整示例:
#!/usr/bin/env python
from neutronclient.v2_0 import client
from credentials import get_credentials
network_name = 'temp_network'
credentials = get_credentials()
neutron = client.Client(**credentials)
try:
body_sample = {'network': {'name': network_name,
'admin_state_up': True}}
netw = neutron.create_network(body=body_sample)
net_dict = netw['network']
network_id = net_dict['id']
print('Network %s created' % network_id)
body_create_subnet = {'subnets': [{'cidr': '192.168.199.0/24',
'ip_version': 4, 'network_id': network_id}]}
subnet = neutron.create_subnet(body=body_create_subnet)
print('Created subnet %s' % subnet)
neutron.delete_network(network_id)
print('Deleted Network %s' % network_id)
finally:
print("Execution Completed")
列出路由:
完整示例:
#!/usr/bin/env python
from neutronclient.v2_0 import client
from credentials import get_credentials
from utils import print_values
try:
credentials = get_credentials()
neutron = client.Client(**credentials)
routers_list = neutron.list_routers(retrieve_all=True)
print_values(routers_list, 'routers')
finally:
print("Execution completed")
列出子网:
#!/usr/bin/env python
from neutronclient.v2_0 import client
from credentials import get_credentials
from utils import print_values
credentials = get_credentials()
neutron = client.Client(**credentials)
subnets = neutron.list_subnets()
print(subnets)
计算:
获得OpenStack凭证:
def get_nova_credentials_v2():
d = {}
d['version'] = '2'
d['username'] = os.environ['OS_USERNAME']
d['api_key'] = os.environ['OS_PASSWORD']
d['auth_url'] = os.environ['OS_AUTH_URL']
d['project_id'] = os.environ['OS_TENANT_NAME']
return d
简单获取:
credentials = get_nova_credentials_v2()
列出服务:
#!/usr/bin/env python
from credentials import get_nova_credentials_v2
from novaclient.client import Client
credentials = get_nova_credentials_v2()
nova_client = Client(**credentials)
print(nova_client.servers.list())
创建server:
#!/usr/bin/env python
import time
from credentials import get_nova_credentials_v2
from novaclient.client import Client
try:
credentials = get_nova_credentials_v2()
nova_client = Client(**credentials)
image = nova_client.images.find(name="cirros")
flavor = nova_client.flavors.find(name="m1.tiny")
net = nova_client.networks.find(label="private")
nics = [{'net-id': net.id}]
instance = nova_client.servers.create(name="vm2", image=image,
flavor=flavor, key_name="keypair-1", nics=nics)
print("Sleeping for 5s after create command")
time.sleep(5)
print("List of VMs")
print(nova_client.servers.list())
finally:
print("Execution Completed")
删除server:
#!/usr/bin/env python
from credentials import get_nova_credentials_v2
from novaclient.client import Client
credentials = get_nova_credentials_v2()
nova_client = Client(**credentials)
servers_list = nova_client.servers.list()
server_del = "vm1"
server_exists = False
for s in servers_list:
if s.name == server_del:
print("This server %s exists" % server_del)
server_exists = True
break
if not server_exists:
print("server %s does not exist" % server_del)
else:
print("deleting server..........")
nova_client.servers.delete(s)
print("server %s deleted" % server_del)
更新server:
#!/usr/bin/env python
from credentials import get_nova_credentials_v2
from novaclient.client import Client
from utils import print_server
credentials = get_nova_credentials_v2()
nova_client = Client(**credentials)
# Change the server_id specific to your environment
server_id = '99889c8d-113f-4a7e-970c-77f1916bfe14'
server = nova_client.servers.get(server_id)
n = server.name
print_server(server)
server.update(name=n +'1')
server_updated = nova_client.servers.get(server_id)
print_server(server_updated)
列出:
#!/usr/bin/env python
from credentials import get_nova_credentials_v2
from novaclient.client import Client
from utils import print_flavors
credentials = get_nova_credentials_v2()
nova_client = Client(**credentials)
flavors_list = nova_client.flavors.list()
print_flavors(flavors_list)
列出浮动ip:
#!/usr/bin/env python
from credentials import get_nova_credentials_v2
from novaclient.client import Client
from utils import print_values_ip
credentials = get_nova_credentials_v2()
nova_client = Client(**credentials)
ip_list = nova_client.floating_ips.list()
print_values_ip(ip_list)
列出hosts:
#!/usr/bin/env python
from credentials import get_nova_credentials_v2
from novaclient.client import Client
from utils import print_hosts
credentials = get_nova_credentials_v2()
nova_client = Client(**credentials)
host_list = nova_client.hosts.list()
print_hosts(host_list)