美文网首页
使用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