CMDB 阿里云部分实现

1. 阿里云 API

https://api.aliyun.com/
阿里云比腾讯云会更麻烦一点.腾讯云通过查询实例,就会返回实例清单,但阿里需要先查询到实例ID,再根据实例ID查询实例对应的磁盘列表.磁盘列表又分为操作系统磁盘和数据磁盘.
在这里插入图片描述

2. 获取实例清单

当发起调用后我们就能拿到了这样一个json的返回
TotalCount 是该地域下一共有多少个ECS实例.
PageSize 是一次查询返回的实例个数,最少1最多100
PageNumber 是这次查询的是第几页
这个就和我们平时做的分页效果一样.
那么就通过这3个值很简单的一个for循环就取到了所有实例列表

{
    
    
	'Instances': {
    
    
		'Instance': [{
    
    
			'ResourceGroupId': '',
			'Memory': 1024,
			'InstanceChargeType': 'PrePaid',
			'Cpu': 1,
			'OSName': 'CentOS  7.9 64位',
			'InstanceNetworkType': 'vpc',
			'InnerIpAddress': {
    
    
				'IpAddress': []
			},
			'ExpiredTime': '2022-07-06T16:00Z',
			'ImageId': 'centos_7_9_x64_20G_alibase_20220426.vhd',
			'EipAddress': {
    
    
				'AllocationId': '',
				'IpAddress': '',
				'InternetChargeType': ''
			},
			'ImageOptions': {
    
    },
			'HostName': 'ixxxxxxxx',
			'VlanId': '',
			'Status': 'Stopped',
			'HibernationOptions': {
    
    
				'Configured': False
			},
			'MetadataOptions': {
    
    
				'HttpTokens': '',
				'HttpEndpoint': ''
			},
			'InstanceId': 'i-2xxxxxxxx',
			'StoppedMode': 'Not-applicable',
			'CpuOptions': {
    
    
				'ThreadsPerCore': 1,
				'Numa': '',
				'CoreCount': 1
			},
			'StartTime': '2022-06-06T07:49Z',
			'DeletionProtection': False,
			'SecurityGroupIds': {
    
    
				'SecurityGroupId': ['sg-2zejxxxxxxxxx']
			},
			'VpcAttributes': {
    
    
				'PrivateIpAddress': {
    
    
					'IpAddress': ['172.17.224.148']
				},
				'VpcId': 'vpc-xxxxxxxxxxx5',
				'VSwitchId': 'vsw-2zxxxxxxxxxxxxm3',
				'NatIpAddress': ''
			},
			'InternetChargeType': 'PayByTraffic',
			'InstanceName': 'test666',
			'DeploymentSetId': '',
			'InternetMaxBandwidthOut': 1,
			'SerialNumber': 'de5xxxxxxxxxxxd3ea3',
			'OSType': 'linux',
			'CreationTime': '2022-06-06T07:48Z',
			'AutoReleaseTime': '',
			'Description': '',
			'InstanceTypeFamily': 'ecs.s6',
			'DedicatedInstanceAttribute': {
    
    
				'Tenancy': '',
				'Affinity': ''
			},
			'PublicIpAddress': {
    
    
				'IpAddress': ['39.107.56.61']
			},
			'GPUSpec': '',
			'NetworkInterfaces': {
    
    
				'NetworkInterface': [{
    
    
					'Type': 'Primary',
					'PrimaryIpAddress': '172.17.224.148',
					'MacAddress': '00:xx:xx:xx:xx:0e',
					'NetworkInterfaceId': 'eni-2xxxxxxxxxn',
					'PrivateIpSets': {
    
    
						'PrivateIpSet': [{
    
    
							'PrivateIpAddress': '172.17.224.148',
							'Primary': True
						}]
					}
				}]
			},
			'SpotPriceLimit': 0.0,
			'DeviceAvailable': True,
			'SaleCycle': '',
			'InstanceType': 'ecs.s6-c1m1.small',
			'SpotStrategy': 'NoSpot',
			'OSNameEn': 'CentOS  7.9 64 bit',
			'IoOptimized': True,
			'ZoneId': 'cn-beijing-j',
			'ClusterId': '',
			'EcsCapacityReservationAttr': {
    
    
				'CapacityReservationPreference': '',
				'CapacityReservationId': ''
			},
			'DedicatedHostAttribute': {
    
    
				'DedicatedHostId': '',
				'DedicatedHostName': '',
				'DedicatedHostClusterId': ''
			},
			'GPUAmount': 0,
			'OperationLocks': {
    
    
				'LockReason': [{
    
    
					'LockReason': 'financial',
					'LockMsg': ''
				}, {
    
    
					'LockReason': 'financial-recycling',
					'LockMsg': ''
				}]
			},
			'InternetMaxBandwidthIn': 100,
			'Recyclable': False,
			'RegionId': 'cn-beijing',
			'CreditSpecification': ''
		}]
	},
	'TotalCount': 1,
	'NextToken': '',
	'PageSize': 100,
	'RequestId': '3BEEExxxxxxxxxxx0B19E',
	'PageNumber': 1
}

3. 通过Python获取实例

这里我们就拿到了实例的id

    # 实例
    def instance_list(self, region_id):
        client = AcsClient(self.secret_id, self.secret_key)
        req = DescribeInstancesRequest()
        try:
            req.add_query_param('RegionId', region_id)
            # 分页查找
            req.set_PageSize(100)
            req.set_MaxResults(100)
            res = client.do_action_with_exception(req)
            data = {
    
    }
            all_num = int(json.loads(res.decode())['TotalCount'])
            if all_num > 100:
                page = all_num // 100 + 2
                data = json.loads(res.decode())
                for i in range(1, page):
                    req.set_PageNumber(i)
                    req.set_PageSize(100)
                    res = client.do_action_with_exception(req)
                    data['Instances']['Instance'].extend(json.loads(res.decode())['Instances']['Instance'])
            else:
                data = json.loads(res.decode())
            print(data)
            return {
    
    'code': 200, 'msg': '执行成功', 'data': data}
        except Exception as e:
            return {
    
    'code': 500, 'msg': e}

4. 获取磁盘清单

这里将刚才获取的实例id和地域id传入DescribeInstances
在这里插入图片描述

5. 得到DescribeInstances返回的Json

可以看到,Json返回了一堆数据,我们只需要遍历Disks下的Disk,将Size累加即可获得所有磁盘的总容量

{
    
    
	"TotalCount": 1,
	"NextToken": "",
	"PageSize": 10,
	"RequestId": "F6xxxxxxxxxxxxxxxxxxxxxx78",
	"PageNumber": 1,
	"Disks": {
    
    
		"Disk": [{
    
    
			"DetachedTime": "",
			"Category": "cloud_efficiency",
			"Description": "",
			"KMSKeyId": "",
			"ResourceGroupId": "",
			"Encrypted": false,
			"Size": 20,
			"DeleteAutoSnapshot": false,
			"DiskChargeType": "PrePaid",
			"Throughput": 103,
			"IOPS": 1960,
			"MultiAttach": "Disabled",
			"Attachments": {
    
    
				"Attachment": [{
    
    
					"AttachedTime": "2022-06-06T07:49:04Z",
					"InstanceId": "i-2xxxxxxxxc",
					"Device": "/dev/xvda"
				}]
			},
			"ExpiredTime": "2022-07-06T16:00Z",
			"ImageId": "centos_7_9_x64_20G_alibase_20220426.vhd",
			"StorageSetId": "",
			"Tags": {
    
    
				"Tag": []
			},
			"Status": "In_use",
			"AttachedTime": "2022-06-06T07:49:04Z",
			"StorageClusterId": "",
			"ZoneId": "cn-beijing-j",
			"InstanceId": "i-2xxxxxxxxxc",
			"SourceSnapshotId": "",
			"ProductCode": "",
			"Device": "/dev/xvda",
			"PerformanceLevel": "",
			"DeleteWithInstance": true,
			"EnableAutomatedSnapshotPolicy": false,
			"EnableAutoSnapshot": true,
			"AutoSnapshotPolicyId": "",
			"DiskName": "",
			"OperationLocks": {
    
    
				"OperationLock": [{
    
    
					"LockReason": "financial"
				}]
			},
			"BdfId": "",
			"Portable": true,
			"Type": "system",
			"SerialNumber": "2zxxxxxxxx35",
			"CreationTime": "2022-06-06T07:48:56Z",
			"RegionId": "cn-beijing",
			"DiskId": "d-2xxxxxxx5"
		}]
	}
}

6. 通过Python获取磁盘

    # 磁盘
    def instance_disk(self, instance_id, region):
        client = AcsClient(self.secret_id, self.secret_key, region)
        request = DescribeDisksRequest()
        request.set_accept_format('json')

        # 2022.0708改的这里想要取磁盘空间信息
        request.set_InstanceId(instance_id)

        try:
            response = client.do_action_with_exception(request)
            return {
    
    'code': 200, 'msg': '执行成功', 'data': response}
        except Exception as e:
            return {
    
    'code': 500, 'msg': e}

7. 通过Python整理ECS信息

        for host in instance_list:
            zone = host['ZoneId']
            instance_id = host['InstanceId']  # 实例ID
            # hostname = host['HostName']
            # 机器名称
            instance_name = host['InstanceName']
            os_version = host['OSName']

            private_ip_list = host['NetworkInterfaces']['NetworkInterface'][0]['PrivateIpSets']['PrivateIpSet']
            private_ip = []
            for ip in private_ip_list:
                private_ip.append(ip['PrivateIpAddress'])

            public_ip = host['PublicIpAddress']['IpAddress']
            cpu = "%s核" %host['Cpu']
            memory = "%sG" %(int(host['Memory']) / 1024)
            # 硬盘信息需要单独获取
            disk = cloud.instance_disk(instance_id, region_id)
            data = json.loads(disk['data'])
            size = 0
            disk_list = data['Disks']['Disk']
            for i in disk_list:
                size += i['Size']
            disk = str(size) + "G"
            # create_date = "2022-01-30"
            create_date = time.strftime("%Y-%m-%d", time.strptime(host['CreationTime'], "%Y-%m-%dT%H:%MZ"))
            # 2022-01-30T04:51Z 需要转换才能存储
            expired_time = time.strftime("%Y-%m-%d %H:%M:%S", time.strptime(host['ExpiredTime'], "%Y-%m-%dT%H:%MZ"))
            idc_name = zone_dic[zone]
            idc = Idc.objects.get(name=idc_name) # 一对多
            data = {
    
    'idc': idc,
                    'name': instance_name,
                    'hostname': instance_id,
                    'ssh_ip': private_ip[0],
                    'ssh_port': ssh_port,
                    'machine_type': 'cloud_vm',
                    'os_version': os_version,
                    'public_ip': public_ip,
                    'private_ip': private_ip,
                    'cpu_num': cpu,
                    'memory': memory,
                    'disk': disk,
                    'put_shelves_date': create_date,
                    'expire_datetime': expired_time,
                    'is_verified': 'verified'}
            server = Server.objects.filter(hostname=instance_id)
            if not server:
                idc_name = zone_dic[zone]
                idc = Idc.objects.get(name=idc_name) # 一对多
                server = Server.objects.create(
                    idc=idc,
                    name=instance_name,
                    hostname=instance_id,
                    ssh_ip=private_ip[0],
                    ssh_port=ssh_port,
                    machine_type='cloud_vm',
                    os_version=os_version,
                    public_ip=public_ip,
                    private_ip=private_ip,
                    cpu_num=cpu,
                    memory=memory,
                    disk=disk,
                    put_shelves_date=create_date,
                    expire_datetime=expired_time,
                    is_verified='verified'
                )
                ## 多对多
                group = ServerGroup.objects.get(id=server_group_id_list)
                server.server_group.add(group)
                res = {
    
    'code': 200, 'msg': '导入云主机成功'}
            else:
                server.update(**data)
                res = {
    
    'code': 200, 'msg': '更新云主机成功'}
        return Response(res)

8. 效果展示

先上效果图,一部分机器打了码.学渗透的小伙伴就别拿这个来练手了,网上机器多得是.请手下留情
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_29974229/article/details/125777948