在上一个博客文章,我展示了如何使用框架管理API来监视由于帐户容量设置错误的配置,该帐户的框架帐户。这可能导致您在云基础架构上的支出超出所需。在此博客中,我将演示如何使用Frame Admin API识别和删除一段时间内未使用的用户量。定期删除未使用的量可以帮助保持云存储成本的降低,并确保适当遵循数据保留政策。
用户量
框架中的用户量有两种类型:个人驱动器和企业配置文件磁盘。这些磁盘的使用在我们的个人驱动器和企业配置文件文档分别。这些卷通常用于外部承包商或教室情况,在这些情况下,用户需要在一段时间内使用这些卷,但不是核心数据管理环境的一部分。在这些用例中,这些卷不是公司数据的长期存储位置,一旦用户完成工作,就可以删除卷。这些旧卷的删除可以由框架控制台内的帧管理员完成,但是如果帧管理员忘记了这些卷,这些卷最终会增加云帐户的存储费用。创建此脚本是为了识别和删除这些卷并通知Slack通道。要使用框架管理API,您将首先需要设置API凭据。此过程已记录这里。由于我想检查运行机器的整个帧“客户”,因此我确保在客户级别设置凭据,并赋予凭据“客户管理员”角色。您还需要获取客户ID,可以在API页面的URL中找到。
脚本设置
就像上一个博客,您需要为框架API和Slack收集一些凭证。
您还需要设置一些变量来定义脚本何时应警告和删除卷,以及什么卷应忽略。
需要定义以下新变量。
_闲置
这是在脚本开始通过Slack警告卷将删除卷之前未使用卷的天数。
_警告日
假设脚本每天运行,这是脚本将发送有关此卷的删除的空缺通知的天数。这使管理员有时间警告用户有关待处理的删除(用户只需要启动框架会话即可重置空闲时钟)或将卷标记为一个例外之一。如果这些事情都没有完成,则脚本将在指定的天数之后删除空闲卷。
_例外
这是一个字符串列表,其中包含不应检查删除的卷的“ ID”。这些ID的格式是Gateway-prod.xxxxxx,其中X是整数。该ID将作为警告的一部分提供,以使管理员更容易确定应豁免哪些卷。
脚本变量的完整列表(包括上一个脚本的变量)如下。
## _clnt_id =“ ”
## _clnt_secret =“ ”
## _cust_id =“ ”
## _slack_url =“ ”
## _idledays = <自上次考虑删除卷以来的天数>
## _warningsdays = <整数警告管理员的天数,该卷将被删除>
## _exceptions = <<可能被排除在可能删除'gateway-prod.1234'>的卷的字符串数组
由于我们要进行一些时间的添加和减法,因此您还需要从DateTime模块导入一些功能
从约会时间进口约会时间,,,,日期,,,,序列塔
API删除请求
帧管理API遵循REST API的最佳实践,并使用不同类型的HTTPS请求来执行不同的功能。这对此任务很重要,因为要删除卷的API利用了HTTPS删除请求而不是HTTPS获取请求。因此,这要求我们创建另一个功能来提出此请求。此DELETE_FRAMEAPICALL如下所示。
防御DELETE_FRAMEAPICALL((api_url,,,,Jsonbody):
#创建签名
时间戳=int((时间。时间(())
签署=“%s%s”%((时间戳,,,,_clnt_id)
签名=HMAC。新的((_clnt_secret,,,,签署。编码(('utf-8'),,,,哈希布。SHA256)。十六世(()
#准备HTTP请求标头
标题={“ X-Frame-Clientid”:_clnt_id,,,,“ X框架Timestamp”:str((时间戳),,,,“ X框架”:签名}
#提出删除请求
r=要求。删除((api_url,,,,标题=标题,,,,数据=Jsonbody)
如果((r。status_code==200):
返回((r。内容)
埃利夫((r。status_code==401):
返回((“未经授权”)
埃利夫((r。status_code==404):
返回((“未找到”)
埃利夫((r。status_code==403):
返回((“错误的请求”)
返回((r。status_code)
Python脚本解释
好的,脚本开始很像带有嵌套循环的容量检查脚本,以涵盖客户实体中的所有帐户。
#________________________________
#Python脚本的主要部分
#________________________________
alert_to_slack((“检查框架教育客户是否有未使用的量\ n _________”)
#获取框架客户下的组织列表
组织=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/organizations?”+_cust_id+“ =&show_deleted = false”)
#将响应转换为JSON
orgs_json=JSON。负载((组织)
#通过每个组织迭代
为了org在orgs_json:
#获取特定组织下的帐户列表
accts=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/?organization_id=”+str((org['ID'这是给出的)+“&Active = true”)
#将响应转换为JSON
accts_json=JSON。负载((accts)
现在,对于每个帐户,我们需要列举该帐户中的用户量。但是,我们只想看到“独立”状态处的卷(因为我们不想尝试使用正在使用的删除量)。我们可以通过在API请求URL末尾添加查询过滤器来做到这一点。我们还需要将响应转换为JSON,以使进一步的处理更加容易。
为了acct在accts_json:
#获取具有独立状态的帐户下的用户量的列表
卷=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/user_volumes/?状态=分离”)
#将响应转换为JSON
卷_json=JSON。负载((卷)
现在,我们迭代卷,我们要做的第一件事就是查看卷是否在异常列表中。如果是这样,我们将跳过设置为true。
为了卷在卷_json['user_volumes'这是给出的:
#初始化如果这是异常列表中的卷,将设置为True的变量
跳过=错误的
#循环浏览异常列表,如果卷的ID在列表中,则将跳过设置为true
为了跳过它在_ Exceptions:
如果((卷['ID'这是给出的==跳过它):
打印((“跳过”+跳过它)
跳过=真的
一旦我们验证它不在异常列表中,我们将查看last_used_time并从当前时间中减去。然后,我们将这种差异转换为整数(中间),这更容易在将来的比较中使用。
#如果跳过不设置为true上方,请获得卷的最后时间
如果((跳过是不是真的):
如果((卷['last_used_time'这是给出的是不是没有任何):
最后=约会时间。strptime((卷['last_used_time'这是给出的,,,,'%y-%m-%dt%h:%m:%S。%fz')。日期(()
#获取自卷上次使用以来的整数数。
之间=((日期。今天(()-最后)。天
现在是两个if语句:一个要确认我们需要警告或删除,然后再删除第二个来确定哪一个。
#检查一下是否闲置于最小天数。
如果((_idledays<之间):
#如果我们在最低天数中闲置,我们会警告吗?或删除
如果((((_idledays+_ Warningdays)<之间):
如果这两个都是正确的,我们需要删除用户量。这涉及使用以前定义的delete_frameapicall函数来创建删除任务。然后,我们可以监视该任务已完成,并在完成后将消息发送给Slack。
#开始删除任务
volid_json={“ user_volume_ids”:卷['ID'这是给出的}
三件事=DELETE_FRAMEAPICALL((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/user_volumes?”,,,,volid_json)
deltask_json=JSON。负载((三件事)
#监视任务ID(每五秒检查一次)以完成删除任务
任务检查=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/任务/”+str((deltask_json['ID'这是给出的))
taskcheck_json=JSON。负载((任务检查)
尽管((taskcheck_json['阶段'这是给出的!=“完毕”):
时间。睡觉((5)
任务检查=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/任务/”+str((deltask_json['ID'这是给出的))
taskcheck_json=JSON。负载((任务检查)
alert_to_slack((“删除”+卷['姓名'这是给出的+“”+卷['类型'这是给出的+“带有`'的身份证+卷['ID'这是给出的+“'”)
如果第一个是正确的,而第二个是错误的,那只是一个警告。
别的:
#如果在警告期内,请打印出警告
alert_to_slack((“用户音量”+卷['姓名'这是给出的+“”+卷['类型'这是给出的+“将被删除”+str((_idledays+_ Warningdays+1-之间)+“几天。放置身份`''+卷['ID'这是给出的+“`在例外列表中,避免删除。”)
那就是一切。
完整的脚本
使用下面的下拉菜单查看并复制整个Python脚本。
POLUMECHECK.PY
#!/bin/env Python
进口哈希布
进口HMAC
进口时间
进口要求
进口基础64
进口JSON
从约会时间进口约会时间,,,,日期,,,,序列塔
#Parameter内容类型应用程序/JSON
## _clnt_id =“ ”
## _clnt_secret =“ ”
## _cust_id =“ ”
## _slack_url =“ ”
## _idledays = <自上次考虑删除卷以来的天数>
## _warnningsdays = <整数警告管理员的天数,该卷将被删除>
## _exceptions = <<可能被排除在可能删除'gateway-prod.1234'>的卷的字符串数组
##功能将警报发送到框架教育松弛频道
#MSG_TEXT:标记形成的文本以发送到Slack
防御alert_to_slack((msg_text):
#使用slack_sdk webhookclient
从Slack_sdk。Webhook进口Webhookclient
#创建并发送形式的消息
Webhook=Webhookclient((_slack_url)
回复=Webhook。发送((
文本=“倒退”,,,,
块=[
{
“类型”:“部分”,,,,
“文本”:{
“类型”:“ mrkdwn”,,,,
“文本”:msg_text
}
}
这是给出的
)
##函数要获得获取框架API信息
#API_URL:使用正确的请求信息形成的API的URL
防御get_frameapicall((api_url):
#创建签名
时间戳=int((时间。时间(())
签署=“%s%s”%((时间戳,,,,_clnt_id)
签名=HMAC。新的((_clnt_secret,,,,签署。编码(('utf-8'),,,,哈希布。SHA256)。十六世(()
#准备HTTP请求标头
标题={“ X-Frame-Clientid”:_clnt_id,,,,“ X框架Timestamp”:str((时间戳),,,,“ X框架”:签名}
#提出请求
r=要求。得到((api_url,,,,标题=标题)
如果((r。status_code==200):
返回((r。内容)
埃利夫((r。status_code==401):
返回((“未经授权”)
埃利夫((r。status_code==404):
返回((“未找到”)
埃利夫((r。status_code==403):
返回((“错误的请求”)
返回((r。status_code)
##函数要使用delete获取框架API删除一些资源
#API_URL:使用正确的请求信息形成的API的URL
#JSONBODY:JSON格式化的删除请求的主体
防御DELETE_FRAMEAPICALL((api_url,,,,Jsonbody):
#创建签名
时间戳=int((时间。时间(())
签署=“%s%s”%((时间戳,,,,_clnt_id)
签名=HMAC。新的((_clnt_secret,,,,签署。编码(('utf-8'),,,,哈希布。SHA256)。十六世(()
#准备HTTP请求标头
标题={“ X-Frame-Clientid”:_clnt_id,,,,“ X框架Timestamp”:str((时间戳),,,,“ X框架”:签名}
#提出请求
r=要求。删除((api_url,,,,标题=标题,,,,数据=Jsonbody)
如果((r。status_code==200):
返回((r。内容)
埃利夫((r。status_code==401):
返回((“未经授权”)
埃利夫((r。status_code==404):
返回((“未找到”)
埃利夫((r。status_code==403):
返回((“错误的请求”)
返回((r。status_code)
#________________________________
#Python脚本的主要部分
#________________________________
alert_to_slack((“检查框架教育客户是否有未使用的量\ n _________”)
#获取框架客户下的组织列表
组织=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/organizations?”+_cust_id+“ =&show_deleted = false”)
#将响应转换为JSON
orgs_json=JSON。负载((组织)
#通过每个组织迭代
为了org在orgs_json:
#获取特定组织下的帐户列表
accts=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/?organization_id=”+str((org['ID'这是给出的)+“&Active = true”)
#将响应转换为JSON
accts_json=JSON。负载((accts)
为了acct在accts_json:
#获取具有独立状态的帐户下的用户量的列表
卷=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/user_volumes/?状态=分离”)
#将响应转换为JSON
卷_json=JSON。负载((卷)
为了卷在卷_json['user_volumes'这是给出的:
#初始化如果这是异常列表中的卷,将设置为True的变量
跳过=错误的
#循环浏览异常列表,如果卷的ID在列表中,则将跳过设置为true
为了跳过它在_ Exceptions:
如果((卷['ID'这是给出的==跳过它):
打印((“跳过”+跳过它)
跳过=真的
#如果跳过不设置为true上方,请获得卷的最后时间
如果((跳过是不是真的):
如果((卷['last_used_time'这是给出的是不是没有任何):
最后=约会时间。strptime((卷['last_used_time'这是给出的,,,,'%y-%m-%dt%h:%m:%S。%fz')。日期(()
#获取自卷上次使用以来的整数数。
之间=((日期。今天(()-最后)。天
#检查一下是否闲置于最小天数。
如果((_idledays<之间):
#如果我们在最低天数中闲置,我们会警告吗?或删除
如果((((_idledays+_ Warningdays)<之间):
#开始删除任务
volid_json={“ user_volume_ids”:卷['ID'这是给出的}
三件事=DELETE_FRAMEAPICALL((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/user_volumes?”,,,,volid_json)
deltask_json=JSON。负载((三件事)
#监视任务ID(每五秒检查一次)以完成删除任务
任务检查=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/任务/”+str((deltask_json['ID'这是给出的))
taskcheck_json=JSON。负载((任务检查)
尽管((taskcheck_json['阶段'这是给出的!=“完毕”):
时间。睡觉((5)
任务检查=get_frameapicall((“ https://api.console.nutanix.com/api/rest/v1/accounts/”+str((acct['ID'这是给出的)+“/任务/”+str((deltask_json['ID'这是给出的))
taskcheck_json=JSON。负载((任务检查)
alert_to_slack((“删除”+卷['姓名'这是给出的+“”+卷['类型'这是给出的+“带有`'的身份证+卷['ID'这是给出的+“'”)
别的:
#如果在警告期内,请打印出警告
alert_to_slack((“用户音量”+卷['姓名'这是给出的+“”+卷['类型'这是给出的+“将被删除”+str((_idledays+_ Warningdays+1-之间)+“几天。放置身份`''+卷['ID'这是给出的+“`在例外列表中,避免删除。”)
别的:
#对于积极使用的卷,不要做任何事情。
#print(acct ['name'])
#print(“ \ t”+vol ['name']+“ \ t”+vol ['type']+“ \ t”+str(vol ['size'])+“ gb \ n”)
alert_to_slack((“ _________ \ ncompleted用户量检查框架教育”)
结论
该脚本旨在每天运行,但其他时间范围可能会起作用。当然,您可以使用变量来满足组织的需求。该脚本的正文也很容易集成到我以前的脚本中,以最大程度地减少您拥有API凭据的位置的数量。如果您确实计划在生产环境中使用这些脚本,我建议您实施更多错误检查/恢复,以应对某些不按计划进行的边缘情况。另请注意,此脚本正在删除卷,因此用户数据可能会面临风险。该脚本仅应在通过完整的生命周期数据保留,备份和破坏政策管理重要的公司数据的环境中使用。