Python+Mongodb 提供服务器信息

1,543次阅读
没有评论
Python+Mongodb

之前博主在使用ansible +阿里云ecs 标签实现主机信息过滤和生成,但是每台ecs绑定的标签数量有限(20个),遂想要自己扩展下,干脆建个简陋的cmdb(只有db:mongodb)o( ̄┰ ̄*)ゞ

大致逻辑

获取 ECS 信息

创建RAM用户和AK/SK

安装SDK依赖

需要用到的api: DescribeInstances,安装依赖:

pip install alibabacloud_ecs20140526==2.1.1

简单样例,获取单挑数据

# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import sys

from typing import List

from alibabacloud_ecs20140526.client import Client as Ecs20140526Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_ecs20140526 import models as ecs_20140526_models


class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client(
        access_key_id: str,
        access_key_secret: str,
    ) -> Ecs20140526Client:
        """
        使用AK&SK初始化账号Client
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config(
            # 您的AccessKey ID,
            access_key_id="access_key_id",
            # 您的AccessKey Secret,
            access_key_secret="access_key_secret"
        )
        # 访问的域名
        config.endpoint = f'ecs-cn-hangzhou.aliyuncs.com'
        return Ecs20140526Client(config)

    @staticmethod
    def main(
        args: List[str],
    ) -> None:
        client = Sample.create_client('accessKeyId', 'accessKeySecret')
        describe_instances_request = ecs_20140526_models.DescribeInstancesRequest(
            region_id='cn-shenzhen',
            page_number=1,
            page_size=1
        )
        # 复制代码运行请自行打印 API 的返回值
        res = client.describe_instances(describe_instances_request).body.to_map()
        print(json.dumps(res))

if __name__ == '__main__':
    Sample.main(sys.argv[1:])

测试结果

{
    "Instances":{
        "Instance":[
            {
                "AutoReleaseTime":"",
                "ClusterId":"",
                "Cpu":8,
                "CpuOptions":{
                    "CoreCount":4,
                    "Numa":"",
                    "ThreadsPerCore":2
                },
                "CreationTime":"2020-05-03T05:11Z",
                "CreditSpecification":"",
                "DedicatedHostAttribute":{
                    "DedicatedHostClusterId":"",
                    "DedicatedHostId":"",
                    "DedicatedHostName":""
                },
                "DedicatedInstanceAttribute":{
                    "Affinity":"",
                    "Tenancy":""
                },
                "DeletionProtection":false,
                "DeploymentSetId":"",
                "Description":"",
                "DeviceAvailable":true,
                "EcsCapacityReservationAttr":{
                    "CapacityReservationId":"",
                    "CapacityReservationPreference":""
                },
                "EipAddress":{
                    "AllocationId":"",
                    "InternetChargeType":"",
                    "IpAddress":""
                },
                "ExpiredTime":"2020-06-03T16:00Z",
                "GPUAmount":0,
                "GPUSpec":"",
                "HibernationOptions":{
                    "Configured":false
                },
                "HostName":"iZz56sxxxxxzkZ",
                "ImageId":"win2016_1607_x64_dtc_zh-cn_40G_alibase_20200311.vhd",
                "ImageOptions":{

                },
                "InnerIpAddress":{
                    "IpAddress":[

                    ]
                },
                "InstanceChargeType":"PrePaid",
                "InstanceId":"i-iZz56sxxxxxzkZ",
                "InstanceName":"launch-advisor-20200503",
                "InstanceNetworkType":"vpc",
                "InstanceType":"ecs.c7.2xlarge",
                "InstanceTypeFamily":"ecs.c7",
                "InternetChargeType":"PayByBandwidth",
                "InternetMaxBandwidthIn":5000,
                "InternetMaxBandwidthOut":20,
                "IoOptimized":true,
                "Memory":16384,
                "MetadataOptions":{
                    "HttpEndpoint":"",
                    "HttpTokens":""
                },
                "NetworkInterfaces":{
                    "NetworkInterface":[
                        {
                            "MacAddress":"00:16:3e:12:a4:1b",
                            "NetworkInterfaceId":"eni-wz9xxx19imewia",
                            "PrimaryIpAddress":"10.200.1.144",
                            "PrivateIpSets":{
                                "PrivateIpSet":[
                                    {
                                        "Primary":true,
                                        "PrivateIpAddress":"10.200.1.144"
                                    }
                                ]
                            },
                            "Type":"Primary"
                        }
                    ]
                },
                "OSName":"Windows Server  2016 \u6570\u636e\u4e2d\u5fc3\u7248 64\u4f4d\u4e2d\u6587\u7248",
                "OSNameEn":"Windows Server  2016 Data Center Edition 64bit Chinese Edition",
                "OSType":"windows",
                "OperationLocks":{
                    "LockReason":[

                    ]
                },
                "PublicIpAddress":{
                    "IpAddress":[
                        "xxxxxxxxxxxxx"
                    ]
                },
                "Recyclable":false,
                "RegionId":"cn-shenzhen",
                "ResourceGroupId":"",
                "SaleCycle":"",
                "SecurityGroupIds":{
                    "SecurityGroupId":[
                        "sg-wz9d0xxxt4i9fg36y3"
                    ]
                },
                "SerialNumber":"00159a9c-74b2-4541-a02xxx29266ca",
                "SpotPriceLimit":0,
                "SpotStrategy":"NoSpot",
                "StartTime":"2020-05-03T05:11Z",
                "Status":"Running",
                "StoppedMode":"Not-applicable",
                "VlanId":"",
                "VpcAttributes":{
                    "NatIpAddress":"",
                    "PrivateIpAddress":{
                        "IpAddress":[
                            "10.200.1.144"
                        ]
                    },
                    "VSwitchId":"vsw-wz9cpxxln62ws0kmw0",
                    "VpcId":"vpc-wz95lwxxtg6pjctear"
                },
                "ZoneId":"cn-shenzhen-e"
            }
        ]
    },
    "NextToken":"4f1d7cc9f51e189029a6ac20e03a54ba666795b580cac90be0b5e8707e68181f",
    "PageNumber":1,
    "PageSize":1,
    "RequestId":"4E4E86B0-D344-5D25-A2D5-54AFCEB0FDE2",
    "TotalCount":357
}

获取单个地域所有样例

# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import sys
import time
from typing import List
import json

from alibabacloud_ecs20140526.client import Client as Ecs20140526Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_ecs20140526 import models as ecs_20140526_models

class EcsInfo:
    def __init__(self):
        pass

    @staticmethod
    def create_client(
            access_key_id: str,
            access_key_secret: str,
    ) -> Ecs20140526Client:
        """
        使用AK&SK初始化账号Client
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config(
            # 您的AccessKey ID,
            access_key_id="access_key_id",
            # 您的AccessKey Secret,
            access_key_secret="access_key_secret"
        )
        # 访问的域名
        config.endpoint = f'ecs.cn-shenzhen.aliyuncs.com'
        return Ecs20140526Client(config)

    @staticmethod
    def main(
            args: List[str],
    ) -> list:
        client = EcsInfo.create_client('accessKeyId', 'accessKeySecret')
        # tag_0 = ecs_20140526_models.DescribeInstancesRequestTag(
        #     key='os',
        #     value='windows'
        # )
        # tag_1 = ecs_20140526_models.DescribeInstancesRequestTag(
        #     key='owner',
        #     value='zhangke'
        # )
        next_token = ''
        describe_instances_request = ecs_20140526_models.DescribeInstancesRequest(
            region_id='cn-shenzhen',
            max_results=10,
            next_token=next_token

            # tag=[
            #     tag_0,
            #     tag_1
            # ]
        )
        res = client.describe_instances(describe_instances_request).body.to_map()
        next_token = res['NextToken']
        # print(next_token)
        instances_list = res['Instances']['Instance']

        while next_token:
            time.sleep(0.5)
            # next_token = res['NextToken']
            describe_instances_request = ecs_20140526_models.DescribeInstancesRequest(
                region_id='cn-shenzhen',
                max_results=10,
                next_token=next_token
            )
            res = client.describe_instances(describe_instances_request).body.to_map()
            next_token = res['NextToken']
            instances_list.extend(res['Instances']['Instance'])

        return instances_list

if __name__ == '__main__':
    #print(sys.argv)
    #print(sys.argv[1:])
    instances = EcsInfo.main(sys.argv[1:])
    print(len(instances))
    for instance in instances:
        print(instance)

测试结果

Python+Mongodb

将数据写入mongodb

# 创建一个Cmdb类
class Cmdb:
    def __init__(self):
        pass
    @staticmethod
    def create_db_client(
            db_user: str,
            db_pass: str,
            db_host: str,
            db_port: str,
            db_name: str
    ) -> object:
        DbClient = pymongo.MongoClient("mongodb://"+ db_user + ':' + db_pass + '@' + db_host + ':' +db_port + "/")
        return  DbClient

    @staticmethod
    def update_ecs_info(instances: list) -> None:
        db_client = Cmdb.create_db_client(
            db_user="cmdbadminxxxx",
            db_pass="123456xxxx",
            db_host="192.168.174.132",
            db_port="27017",
            db_name="cmdb"
        )

        mydb =  db_client["cmdb"]
        mycol = mydb["ecsinfo2"]
        for doc in instances:
            # 根据实例id唯一进行查找判断是更新还是新增
            query = {'InstanceId': doc['InstanceId']}
            res = mycol.find_one(query)
            # 后期新增自定义的字段EcsTag,需要保留
            if res and 'EcsTag' in res:
                doc['EcsTag'] = res['EcsTag']
                print("==[update]==",doc)
                mycol.update_one(query,{"$set": doc})
            else:
                doc['EcsTag'] = []
                print("==[insert]==",doc)
                x = mycol.insert_one(doc)

测试更新或新增

Python+Mongodb

从Mongodb获取ecs信息

# 在Cmdb类中创建查询方法
    @staticmethod
    def get_ecs_info(
            query: dict,
    ) -> None:
        db_client = Cmdb.create_db_client(
            db_user="cmdbadminxxxx",
            db_pass="123456xxxx",
            db_host="192.168.174.132",
            db_port="27017",
            db_name="cmdb"
        )

        mydb =  db_client["cmdb"]
        mycol = mydb["ecsinfo2"]
        # print(query)
        query_lists = list(mycol.find(query))
        return query_lists

测试查询结果

Python+Mongodb

新增自定义字段

在原有的数据中已存在Tag字段,该字段是从阿里云ECS openapi获取的ecs 标签,想了想还是新建一个字段EcsTag吧~

# 扩展字段如下,可以自行再扩展如:增加用户信息,创建时间等
        {
            "EcsTag": [
                {
                    'ProjectName': 'demo_project1',
                    'ProjectService': 'demo_service1',
                    'BuildVersion': '#1254',
                    'env': 'test',
                    'status': 'running'
                },
                {
                    'ProjectName': 'demo_project2',
                    'ProjectService': 'demo_service2',
                    'BuildVersion': '#1254',
                    'env': 'test',
                    'status': 'running'
                }
            ]
        }

新增打标方法

    # 再原有的Cmdb类中新增一个打标方法,一次只更新一台ecs的一个或多个标签
    @staticmethod
    def update_ecs_info_ecstag(query:dict,data:list)->None:
        db_client = Cmdb.create_db_client(
            db_user="cmdbadminxxxx",
            db_pass="123456xxxx",
            db_host="192.168.174.132",
            db_port="27017",
            db_name="cmdb"
        )

        mydb =  db_client["cmdb"]
        mycol = mydb["ecsinfo2"]

        query = query
        data = data

        # 先获取已有标签
        res = mycol.find_one(query,{'_id':0,"EcsTag":1})
        res_list = res['EcsTag']
        print(len(res_list),res_list)

        # 处理已有标签的更新或新增数据的合并
        if res_list:
            datatmp = data[:]
            for i in data:
                for j in res_list:
                    if i['ProjectName'] == j['ProjectName'] and i['ProjectService'] == j['ProjectService']:
                        # print(res_list.index(j))
                        print("==[update]==",i)
                        update_query = {
                            '$and': [
                                query,
                                {
                                    'EcsTag.ProjectName': j['ProjectName'],
                                    'EcsTag.ProjectService': j['ProjectService']
                                }
                            ]
                        }
                        mycol.update_one(update_query ,{
                            '$set': {
                                'EcsTag.$': i
                            }
                        })
                        datatmp.remove(i)

            print("==[insert]==", datatmp)
            mycol.update_one(query, {'$addToSet': {'EcsTag': {'$each': datatmp}}})
            
        else:
            print("==[insert]==",data)
            mycol.update_one(query, {'$set': {'EcsTag': data }})

        db_client.close()

测试更新

Python+Mongodb
Python+Mongodb

调用get_ecs_info()查询项目所在服务器

# 先自行打标~
if __name__ == '__main__':
    tagkey_query = {'EcsTag.ProjectName': 'demo_project2','EcsTag.ProjectService': 'demo_service2'}
    tagkey_option = {'_id':0,'InstanceId':1,'VpcAttributes.PrivateIpAddress':1}
    ecs_infos = Cmdb.get_ecs_info(tagkey_query,tagkey_option)
    print(len(ecs_infos))
    for i in ecs_infos:
        print(i)
Python+Mongodb
196
xadocker
版权声明:本站原创文章,由 xadocker2020-12-26发表,共计8404字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码
载入中...