美文网首页
使用OpenStack API刷network和vm

使用OpenStack API刷network和vm

作者: ljyfree | 来源:发表于2019-07-05 17:18 被阅读0次

实现对network/subnet/vm的快速添加和删除

  • 首先电脑上安装python 2.7和openstacksdk这个package
  • 目录下有两个文件,一个是auto.py,一个是openstack_util.py
  • openstack_util.py,使用时注意project_id的赋值
# coding: utf-8

import sys
reload(sys)
sys.setdefaultencoding('utf8')
import os
import re
import datetime
import openstack


__all__ = ['get_connection', 'get_network', 'get_network_list', 'get_subnet', 'get_subnet_list', 'get_flavor',
           'get_image', 'get_image_list', 'delete_network', 'create_network', 'create_subnet',
           'create_keypair', 'create_vm', 'delete_vm', 'delete_vm_with_regex', 'delete_network_with_regex']


default_auth = {
    "project_id": "afa9ef6caea84c72b0a7a07022ae6d80",
    "user_domain_id": "default",
    'username': "admin",
    'password': "yunshan3302",
    "auth_url": "http://10.25.71.90:5000/v3"
}


class GetObjFail(Exception):
    pass


def singleton(cls):
    """
    @summary: 将初始化好的实例放置到instances中, 以后再次初始化时,直接提取初始化好的实例
    """
    instances = {}

    def _singleton(auth, *args, **kw):
        # 如果auth参数有变更,则重新初始化,实现的伪单例模式
        if cls not in instances:
            instances[cls] = cls(auth, *args, **kw)
        elif auth != instances[cls].auth:
            instances[cls] = cls(auth, *args, **kw)
        # print 'instances: ', instances
        return instances[cls]

    return _singleton


@singleton
class Connection(object):
    def __init__(self, auth=None, auth_expire=None):
        """
        :param auth: 认证参数。格式如下:
                     auth = {
                             "project_id": "59840d75b6c046b1885cb58dab9279ea",
                             "user_domain_id": "default",
                             'username': "admin",
                             'password': "yunshan3302",
                             "auth_url": "http://10.25.178.10:5000/v3"
                            }
        :param auth_expire: token超时时间,默认为1h
        """
        self.auth = auth if auth is not None else default_auth
        self.auth_type = 'password'
        self.conn = None
        self._init_conn_time = None
        self._get_conn_time = None
        self.auth_expire = auth_expire if auth_expire is not None else \
            datetime.timedelta(hours=1)  # expire time: 1h
        self._init_conn()

    def _init_conn(self):
        self.conn = openstack.connect(auth=self.auth, auth_type=self.auth_type)
        self._init_conn_time = datetime.datetime.now()

    def _time_expired(self):
        return self._get_conn_time - self._init_conn_time >= self.auth_expire

    def get_connection(self):
        self._get_conn_time = datetime.datetime.now()
        if self.conn is None or self._time_expired():
            self.conn = openstack.connect(auth=self.auth, auth_type=self.auth_type)
            self._init_conn_time = datetime.datetime.now()
        return self.conn


def get_connection(auth=default_auth):
    # type: () -> object
    return Connection(auth=auth).get_connection()


def get_image(image_id, connection=None, ignore_missing=False):
    """
    @summary: 根据image_name获取image对象(openstack.compute.v2.image.ImageDetail)
    :param image_id: str, image uuid
    :param connection: Connection object
    :param ignore_missing: 如果未找到,是否raise fail,默认raise
    :return: image对象(openstack.compute.v2.image.ImageDetail) or raise get image failed
    """
    conn = connection if connection is not None else get_connection()
    for image in conn.compute.images():
        if image.id == image_id:
            return image
    if not ignore_missing:
        raise GetObjFail('get image <{}> failed!'.format(image_id))


def get_image_list(image_name, connection=None):
    """
    @summary: 根据image_name获取image对象列表(image名称可以重复)
    :param image_name: str, image名称
    :param connection: Connection object
    :return: image对象列表
    """
    conn = connection if connection is not None else get_connection()
    image_lst = []
    for image in conn.compute.images():
        if image.name == image_name:
            image_lst.append(image)
    return image_lst


def get_flavor(flavor_name, connection=None, ignore_missing=False):
    """
    @summary: 根据flavor_name获取flavor对象
    :param flavor_name: str, flavor名称
    :param connection: Connection object
    :param ignore_missing: 如果未找到,是否raise fail,默认raise
    :return: flavor对象(openstack.compute.v2.flavor.FlavorDetail)
    """
    conn = connection if connection is not None else get_connection()
    for flavor in conn.compute.flavors():
        if flavor.name == flavor_name:
            return flavor
    if not ignore_missing:
        raise GetObjFail('get flavor <{}> failed!'.format(flavor_name))


def get_network_list(network_name, connection=None):
    """
    @summary: 根据network_name获取network对象的列表(network名称可以重复)
    :param network_name: str, network名称
    :param connection: Connection object
    :return: network对象列表
    """
    conn = connection if connection is not None else get_connection()
    net_lst = []
    for network in conn.network.networks():
        if network.name == network_name:
            net_lst.append(network)
    return net_lst


def get_network(network_id, connection=None, ignore_missing=False):
    """
    @summary: 根据network_id获取network对象
    :param network_id: str, network uuid
    :param connection: Connection object
    :param ignore_missing: 如果未找到,是否raise fail,默认raise
    :return: network对象
    """
    conn = connection if connection is not None else get_connection()
    for network in conn.network.networks():
        if network.id == network_id:
            return network
    if not ignore_missing:
        raise GetObjFail('get network <{}> failed!'.format(network_id))


def get_subnet_list(subnet_name, connection=None):
    """
    @summary: 根据subnet_name获取subnet对象列表(subnet名称可以重复)
    :param subnet_name: str, subnet名称
    :param connection: Connection object
    :return: subnet对象列表
    """
    conn = connection if connection is not None else get_connection()
    subnet_lst = []
    for subnet in conn.network.subnets():
        if subnet.name == subnet_name:
            subnet_lst.append(subnet)
    return subnet_lst


def get_subnet(subnet_id, connection=None, ignore_missing=False):
    """
    @summary: 根据subnet_id获取subnet对象
    :param subnet_id: str, subnet uuid
    :param connection: Connection object
    :param ignore_missing: 如果未找到,是否raise fail,默认raise
    :return: subnet对象
    """
    conn = connection if connection is not None else get_connection()
    for subnet in conn.network.subnets():
        if subnet.id == subnet_id:
            return subnet
    if not ignore_missing:
        raise GetObjFail('get subnet <{}> failed!'.format(subnet_id))


def create_network(net_name, connection=None, **kwargs):
    """
    @summary: 创建租户网络
    :param net_name: 网络名称
    :param connection: Connection object
    :param kwargs: 支持参数及默认值如下:
                   shared=False
                   admin_state_up=True
                   external=False
                   provider=None
                   project_id=None
                   availability_zone_hints=None
                   port_security_enabled=None
                   mtu_size=None
    :return: network object
    """
    conn = connection if connection is not None else get_connection()
    return conn.network.create_network(name=net_name, **kwargs)


def create_subnet(network_id, subnet_name, cidr,
                  ip_version=4, enable_dhcp=False, connection=None, **kwargs):
    """
    @summary: 为network创建子网,返回subnet对象
    :param network_id: network uuid
    :param subnet_name: str, 子网名称
    :param cidr: str, 格式:'10.8.8.0/24'
    :param ip_version: 默认为4
    :param enable_dhcp: 是否开启dhcp,默认关闭
    :param connection: Connection object (openstack.connect.Connection)
    :param kwargs: 格式及默认值如下:
                   tenant_id=None
                   allocation_pools=None
                   gateway_ip=None
                   disable_gateway_ip=False
                   dns_nameservers=None
                   host_routes=None
                   ipv6_ra_mode=None
                   ipv6_address_mode=None
                   prefixlen=None
                   use_default_subnetpool=False
    :return: subnet object
    """
    conn = connection if connection is not None else get_connection()
    return conn.network.create_subnet(
        network_id=network_id,
        name=subnet_name,
        cidr=cidr,
        ip_version=ip_version,
        enable_dhcp=enable_dhcp,
        **kwargs
    )


def delete_network(network_id, ignore_missing=False, connection=None):
    conn = connection if connection is not None else get_connection()
    # 如果是新创建的network,并创建了sunbet, 需要重新get该network对象,原有创建的network没有subnet
    network = get_network(network_id, ignore_missing=ignore_missing)
    # TODO 需要确认是否需要先清除port, 目前来看木有问题`o`
    # 先删除subnet
    for subnet_id in network.subnet_ids:
        conn.network.delete_subnet(subnet_id, ignore_missing=ignore_missing)

    # 再删除network
    conn.network.delete_network(network.id, ignore_missing=ignore_missing)


def create_keypair(key_name, key_dir, keyfile, connection=None):
    conn = connection if connection is not None else get_connection()
    keypair = conn.compute.find_keypair(key_name)
    if keypair:
        # 如果key_name的keypair已经存在,删除keypair
        conn.compute.delete_keypair(key_name)
    keypair = conn.compute.create_keypair(name=key_name)
    if not os.path.exists(key_dir):
        os.mkdir(key_dir)
    keyfile = os.path.join(key_dir, keyfile)
    with open(keyfile, 'w') as f:
        f.write("%s" % keypair.private_key)
    # os.chmod()
    return keypair, keyfile


def create_vm(vm_name, image_name, flavor_name, network_id,
              connection=None, keypair=None, keyfile=None):
    conn = connection if connection is not None else get_connection()
    image = conn.compute.find_image(image_name)
    flavor = conn.compute.find_flavor(flavor_name)
    if keypair is not None and keyfile is not None:
        vm = conn.compute.create_server(
            name=vm_name, image_id=image.id, flavor_id=flavor.id,
            networks=[{"uuid": network_id}], key_name=keypair.name, config_drive=True)
    else:
        vm = conn.compute.create_server(
            name=vm_name, image_id=image.id, flavor_id=flavor.id,
            networks=[{"uuid": network_id}], config_drive=True,
            # max_count=5,
        )
    vm = conn.compute.wait_for_server(vm)
    # print("ssh -i {key} root@{ip}".format(
    #     key=keyfile,
    #     ip=vm.access_ipv4))
    return vm


def delete_vm(vm, connection=None):
    conn = connection if connection is not None else get_connection()
    conn.compute.delete_server(vm)


def delete_all_vms(connection=None):
    conn = connection if connection is not None else get_connection()
    for vm in conn.compute.servers():
        conn.compute.delete_server(vm)


def delete_vm_with_regex(name_pattern, connection=None):
    conn = connection if connection is not None else get_connection()
    if isinstance(name_pattern, basestring):
        name_pattern = re.compile(name_pattern)
    for vm in conn.compute.servers():
        if re.search(name_pattern, vm.name):
            conn.compute.delete_server(vm)


def delete_network_with_regex(net_pattern, connection=None):
    conn = connection if connection is not None else get_connection()
    if isinstance(net_pattern, basestring):
        net_pattern = re.compile(net_pattern)
    for net in conn.network.networks():
        if re.search(net_pattern, net.name):
            for subnet_id in net.subnet_ids:
                conn.network.delete_subnet(subnet_id, ignore_missing=False)
            # 再删除network
            conn.network.delete_network(net.id, ignore_missing=False)


if __name__ == '__main__':
    import pdb
    conn = get_connection()
    pdb.set_trace()
  • 用于操作的脚本,按需注释/去除注释,然后运行
#!/usr/bin/python
# coding: utf-8
from openstack_util import *
import time
net_num = 2
vm_per_net = 3

for net_id in range(1,net_num+1):
    net = create_network('autonet'+str(net_id))
    subnet = create_subnet(net.id, 'autosubnet'+str(net_id), '10.99.'+str(net_id)+'.0/24', ip_version=4, enable_dhcp=False, connection=None)
    print net
    print subnet
    for vm_id in range(1,vm_per_net+1):
        vm = create_vm('autovm'+"-"+str(net_id)+"-"+str(vm_id), 'cirros', 'tiny', str(net.id), connection=None, keypair=None, keyfile=None)
        print vm

# delete_vm_with_regex(r'autovm-\d+-\d', connection=None)
# time.sleep(5)
# delete_network_with_regex(r'autonet\d+', connection=None)

相关文章

网友评论

      本文标题:使用OpenStack API刷network和vm

      本文链接:https://www.haomeiwen.com/subject/asnehctx.html