华为云API

PGSQL

Grafana的数据源

安装PostgreSQL

sudo yum install -y gcc gcc-c++ make openssl-devel readline-devel zlib-devel libuuid-devel
./configure
make && make install

useradd -r -m -s /sbin/nologin postgres  # 创建postgres用户
# 创建数据目录(自定义路径,比如/var/lib/pgsql/data)
mkdir -p /var/lib/pgsql/data

# 改属主为postgres(关键!否则初始化失败)
chown -R postgres:postgres /var/lib/pgsql
chmod 700 /var/lib/pgsql/data  # 严格权限,仅postgres可访问

su postgres -s /bin/bash -c "/usr/local/pgsql/bin/initdb -D /var/lib/pgsql/data"  # 初始化数据库
su postgres -s /bin/bash -c "/usr/local/pgsql/bin/pg_ctl -D /var/lib/pgsql/data -l /var/lib/pgsql/logfile start"  # 启动数据库服务
su postgres -s /bin/bash -c "/usr/local/pgsql/bin/psql -c \"ALTER USER postgres WITH PASSWORD 'HYH@123.com';\""  # 修改用户密码
su postgres -s /bin/bash -c "/usr/local/pgsql/bin/psql -c \"CREATE DATABASE pg_db;\""  # 创建数据库

Python连接PostgreSQL

wget https://files.pythonhosted.org/packages/source/p/psycopg2/psycopg2-2.9.9.tar.gz
tar -zxvf psycopg2-2.9.9.tar.gz
cd psycopg2-2.9.9
mkdir -p /usr/local/lib64/python3.7/site-packages/
chmod 755 /usr/local/lib64/python3.7/site-packages/
yum install -y postgresql-devel python3-devel  # 安装依赖库
python3 setup.py install   # 安装psycopg2  --user

Nginx

作用:通过nginx配置,实现文件目录的访问。
img

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    include /etc/nginx/conf.d/*.conf;

    server {
        listen 80;
        server_name 10.134.59.147;  # 你的服务器IP
        # 匹配访问路径 /hcs/ecs
        location /hcs/ecs {
            alias /hcs/ecs;  # 实际文件路径
            # 核心:开启目录浏览
            autoindex on;
            # 美化:显示文件大小、修改时间,用表格布局
            autoindex_exact_size off;  # 显示友好单位(KB/MB)
            autoindex_localtime on;    # 显示本地时间(而非UTC)
            autoindex_format html;    # 输出HTML格式(默认就是html)
            # 允许下载(默认已开启)
            charset utf-8;  # 避免中文文件名乱码
        }
    }
}

访问路径:http://10.134.59.147/hcs/ecs

crontab

vi crontab.sh

#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echo "===== 执行时间:$(date) =====" >> /wise/log_crontab.log
/usr/bin/python3 -u /wise/py/ECS.py >> /wise/log_crontab.log 2>&1
echo "==================================================================================================" >> /wise/log_crontab.log
chmod +x crontab.sh

crontab -e
# 分 时 日 月 周 执行脚本(日志输出到指定文件,方便排查)
0 8 * * * su - root -c "/bin/bash /wise/crontab.sh"  # su - root 切换到root用户执行脚本,避免权限问题
crontab -l  # 查看已添加的定时任务

# 重启 crond 服务(确保生效)
systemctl restart crond
systemctl enable crond

华为云API

配置AK/SK

登录ManageOne运营面。
在右上角单击用户图标,选择“个人设置”。
在“个人设置”页面选择“管理访问密钥”页签。
单击“新增访问密钥”,新建AK/SK。
单击“确定”,自动下载访问密钥文件(credentials.csv),文件中包含AK和SK信息。

查询project_id

OC账号-->云服务管理中心-->组织-->企业项目管理-->点击企业项目名称-->查看详情

配置环境变量

vim ~/.bashrc

export CS_USERNAME=huangyihao
export CS_PASSWORD=Password

export SC_USERNAME=huangyihao_pro
export SC_PASSWORD=Password

source ~/.bashrc

请求URL

{URI-scheme}: //{Endpoint}/{resource-path}?{query-string}

参数 描述
URI-scheme 表示用于传输请求的协议,当前所有API均采用HTTPS协议。
Endpoint 指定承载REST服务端点的服务器域名或IP,不同服务不同区域的Endpoint不同。
resource-path 资源路径,也即API访问路径。从具体API的URI模块获取,例如“获取用户Token”API的resource-path为“/v3/auth/tokens”。
query-string 查询参数,是可选部分,并不是每个API都有查询参数。查询参数前面需要带一个“?”,形式为“参数名=参数取值”,例如“limit=10”,表示查询不超过10条数据。多个查询参数之间使用“&”隔开。
以下信息仅适用于我的环境
运营/租户端即SC功能调测就使用sc.hcs.ciccwm.com
运维端OC功能调测就使用oc.hcs.ciccwm.com
IAM :iam-apigateway-proxy.cn-sz.hcs.ciccwm.com

完整代码1

# -*- coding: utf-8 -*-
import requests
import json
import os
import pandas as pd
import psycopg2
from psycopg2 import OperationalError, Error
from datetime import datetime

requests.packages.urllib3.disable_warnings()

SC_USERNAME = os.getenv("SC_USERNAME")
SC_PASSWORD = os.getenv("SC_PASSWORD")
SC_DOMAIN = "中金财富-生产环境"

CS_USERNAME = os.getenv("CS_USERNAME")
CS_PASSWORD = os.getenv("CS_PASSWORD")
CS_DOMAIN = "中金财富-测试环境"

SYS_USERNAME = os.getenv("SYS_USERNAME")
SYS_PASSWORD = os.getenv("SYS_PASSWORD")
SYS_DOMAIN = 'AdvanceService_System_VDC'

class HCS_API:
    def __init__(self, username, password, domain):
        self.username = username
        self.password = password
        self.domain = domain
        self.enterprise_projects_list = []
        self.ecs_num_list = []
        self.headers = {
            "accept": "text/xml, application/xml, application/xhtml+xml, application/json",
            "accept-charset": "utf-8",
            "Content-Type": "application/json"
            }
        self.token = None  # 初始化 token 实例属性
        self.now = datetime.now()
        self.day = str(self.now.date())

    def get_token(self):  # 获取 token
        token_url = "https://iam-apigateway-proxy.cn-sz.hcs.ciccwm.com:443/v3/auth/tokens"
        body = {
                "auth": {
                    "identity": {
                        "methods": ["password"],
                        "password": {
                            "user": {
                                "name": self.username,
                                "password": self.password,
                                "domain": {"name": self.domain}
                                }
                            }
                        },
                    "scope": {"domain": {"name": self.domain}}
        }}
        r = requests.post(token_url, headers=self.headers, data=json.dumps(body), verify=False)
        self.token = r.headers.get("X-Subject-Token")
        return self.token

    def get_enterprise_projects(self):  # 获取企业项目
        enpo_url = "https://10.166.12.1:443/v1.0/enterprise-projects"
        self.headers["X-Auth-Token"] = self.token
        enpo = requests.get(enpo_url, headers=self.headers, verify=False).json()
        self.enpo_list = []
        for info in enpo['enterprise_projects']:
            self.enterprise_projects_list.append((self.domain, info['name'], str(info['id']), info['description']))
        return self.enterprise_projects_list

    def get_ecs(self):
        '''
        CLOUD_VM	弹性云服务器
        CLOUD_VM_NOVA	弹性云服务器(Nova)
        CLOUD_VOLUME	云硬盘
        SYS_DataCenter	数据中心
        SYS_Rack	机柜
        SYS_Region	区域
        SYS_StoragePool	存储池
        SYS_BusinessRegion	业务区域
        SYS_ResourcePool	资源池
        SYS_Azone	可用区
        '''
        ecs_url = "https://oc.cn-sz.hcs.ciccwm.com/rest/cmdb/v1/instances/CLOUD_VM_NOVA"
        self.headers["X-Auth-Token"] = self.token
        params = {
            "pageSize":1000,
            "pageNo":1
        }
        ecs = requests.get(ecs_url, params=params, headers=self.headers, verify=False).json()
        dataframe = pd.DataFrame(ecs['objList'])
        self.ecs_num_list.append((self.day, len(dataframe), self.domain))
        return dataframe, self.ecs_num_list

    def df_to_excel(self, DF):
        Excel_name = '/hcs/ecs/HCS_' + self.day + '.xlsx'
        DF.to_excel(Excel_name, index=False)
        print(f"成功写入到Excel {Excel_name} 中")

class PGsql:
    def __init__(self, ip, port, user, password):
        self.ip = ip
        self.port = port
        self.user = user
        self.password =password

    def connect_db(self, db):
        """连接到PostgreSQL数据库"""
        conn = None
        try:
            # 连接参数(根据实际环境修改)
            conn = psycopg2.connect(host=self.ip, port=self.port, database=db, user=self.user, password=self.password)
            print("数据库连接成功!")
        except OperationalError as e:
            print(f"连接失败:{e}")
        return conn

    def truncate_table(self, conn, table_name):
        if not conn:
            return
        truncate_sql = 'TRUNCATE TABLE ' + table_name
        conn.cursor().execute(truncate_sql)
        conn.commit()
        print(table_name + '已清空!')

    def insert_data(self, conn, pgsql_data, pgsql_sql):
        now = datetime.now()
        day = str(now.date())
        if not conn:
            return
        try:
            cur = conn.cursor()
            cur.executemany(pgsql_sql, pgsql_data)
            conn.commit()
            print(f"成功插入 {cur.rowcount} 条数据")  # cur.rowcount返回受影响的行数
        except Error as e:
            print(f"插入失败:{e}")
        finally:
            if cur:
                cur.close()

print('================获取Token=====================')
CS_HCS = HCS_API(CS_USERNAME, CS_PASSWORD, CS_DOMAIN)
SC_HCS = HCS_API(SC_USERNAME, SC_PASSWORD, SC_DOMAIN)
SYS_HCS = HCS_API(SYS_USERNAME, SYS_PASSWORD, SYS_DOMAIN)
CS_HCS.get_token()
SC_HCS.get_token()
SYS_HCS.get_token()
print('================获取ECS数据===================')
CS_ECS, CS_NUM = CS_HCS.get_ecs()
SC_ECS, SC_NUM = SC_HCS.get_ecs()
SYS_ECS, SYS_NUM = SYS_HCS.get_ecs()
print('================ECS写入到Excel================')
All_Ecs = pd.concat([CS_ECS, SC_ECS, SYS_ECS], axis=0, ignore_index=True)  # axis=0:上下拼接;axis=1:左右拼接;ignore_index=True:忽略原DataFrame的索引
SC_HCS.df_to_excel(All_Ecs)  # 将DataFrame写入Excel
print('================获取ECS企业项目数据===========')
CS_ENPO = CS_HCS.get_enterprise_projects()
SC_ENPO = SC_HCS.get_enterprise_projects()
SYS_ENPO =SYS_HCS.get_enterprise_projects()
print('================数据写入到PGSQL===============')
CPGsql = PGsql('127.0.0.1', 5432, 'postgres', CS_PASSWORD)
PG_conn = CPGsql.connect_db('pg_db')
CPGsql.truncate_table(PG_conn, 'enterprise_projects')
All_ENPO = CS_ENPO + SC_ENPO + SYS_ENPO
ALL_ECS_NUM = CS_NUM + SC_NUM + SYS_NUM
enpo_sql = "INSERT INTO enterprise_projects (domain, name, id, description) VALUES (%s, %s, %s, %s)"
ecs_num_sql = "INSERT INTO ecs_num (timestamp, num, domain) VALUES (%s, %s, %s)"
CPGsql.insert_data(PG_conn, All_ENPO, enpo_sql)
CPGsql.insert_data(PG_conn, ALL_ECS_NUM, ecs_num_sql)
PG_conn.close()

完整代码2

# -*- coding: utf-8 -*-
import requests
import json
import os
import pandas as pd
from datetime import datetime

requests.packages.urllib3.disable_warnings()

SC_USERNAME = os.getenv("SC_USERNAME")
SC_PASSWORD = os.getenv("SC_PASSWORD")
SC_DOMAIN = "中金财富-生产环境"

CS_USERNAME = os.getenv("CS_USERNAME")
CS_PASSWORD = os.getenv("CS_PASSWORD")
CS_DOMAIN = "中金财富-测试环境"

SYS_USERNAME = os.getenv("SYS_USERNAME")
SYS_PASSWORD = os.getenv("SYS_PASSWORD")
SYS_DOMAIN = 'AdvanceService_System_VDC'

class HCS_API:
    def __init__(self, username, password, domain):
        self.username = username
        self.password = password
        self.domain = domain
        self.headers = {
            "accept": "text/xml, application/xml, application/xhtml+xml, application/json",
            "accept-charset": "utf-8",
            "Content-Type": "application/json"
            }
        self.token = None
        self.day = str(datetime.now().date())
        self.Excel_name = "HCS_" + self.day + ".xlsx"
        if not os.path.exists(self.Excel_name):
            pd.DataFrame().to_excel(self.Excel_name, index=False)

    def get_token(self):  # 获取 token
        token_url = "https://iam-apigateway-proxy.cn-sz.hcs.ciccwm.com:443/v3/auth/tokens"
        body = {
                "auth": {
                    "identity": {
                        "methods": ["password"],
                        "password": {
                            "user": {
                                "name": self.username,
                                "password": self.password,
                                "domain": {"name": self.domain}
                                }
                            }
                        },
                    "scope": {"domain": {"name": self.domain}}
        }}
        r = requests.post(token_url, headers=self.headers, data=json.dumps(body), verify=False)
        self.token = r.headers.get("X-Subject-Token")

    def get_classes(self, className):
        classes_url = "https://oc.cn-sz.hcs.ciccwm.com/rest/cmdb/v1/instances/" + className
        self.headers["X-Auth-Token"] = self.token
        params = {
            "pageSize":1000,
            "pageNo":1
        }
        classes = requests.get(classes_url, params=params, headers=self.headers, verify=False).json()
        dataframe = pd.DataFrame(classes['objList'])
        dataframe['domain_type'] = self.domain
        return dataframe

    def write_to_excel(self, dataframe,sheetname):
        with pd.ExcelWriter(self.Excel_name, engine="openpyxl", mode="a") as writer:
            dataframe.to_excel(writer, sheet_name=sheetname, index=False)

print('================获取Token=====================')
CS_HCS = HCS_API(CS_USERNAME, CS_PASSWORD, CS_DOMAIN)
SC_HCS = HCS_API(SC_USERNAME, SC_PASSWORD, SC_DOMAIN)
SYS_HCS = HCS_API(SYS_USERNAME, SYS_PASSWORD, SYS_DOMAIN)
CS_HCS.get_token()
SC_HCS.get_token()
SYS_HCS.get_token()
print('================获取数据======================')
sheet_name = ['CLOUD_VM', 'CLOUD_VM_NOVA', 'CLOUD_VOLUME', 'SYS_DataCenter', 'SYS_Rack', 'SYS_Region', 'SYS_StoragePool', 'SYS_BusinessRegion', 'SYS_ResourcePool', 'SYS_Azone']
for className in sheet_name:
    CS_DF = CS_HCS.get_classes(className)
    SC_DF = SC_HCS.get_classes(className)
    SYS_DF = SYS_HCS.get_classes(className)
    All_DF = pd.concat([CS_DF, SC_DF, SYS_DF], axis=0, ignore_index=True).drop_duplicates()  # axis=0 表示按行合并,ignore_index=True 表示不保留原来的索引, drop_duplicates() 表示去除重复的行
    CS_HCS.write_to_excel(All_DF, className)
    print('================' + className + '成功写入到Excel============')

故障中心

access_denied 错误主要是权限问题,您需要获取项目级token或申请相应的运维权限才能访问容量管理API

posted @ 2026-03-20 17:17  WiseHYH  阅读(2)  评论(0)    收藏  举报