(已失效)Vultr免费backup功能,如何实现自动定时快照?

  1. 有vultr的童鞋们想必都知道,backup和snapshot两者之间的区别并不大,都能实现备份。
  2. backup唯一好处就是自动备份,不需要像snapshot一样每次都手动创建。
  3. 有没有办法实现snapshot也自动化呢? 毕竟免费啊免费啊。答案是肯定的,请看作者的表演
  • 熟悉一门开发语言(作者用Python进行演示)
  • 查阅vultr官方api文档

登陆vultr管理界面,从右上角头像进入api界面,然后点击[enable]按钮,并开启允许所有的ipv4地址使用该api key

  1. 仔细观察api的url可以发现一定的规律
    • 例如显示快照列表:/v1/snapshot/list
    • 例如创建sshkey:/v1/sshkey/create
  2. 那么我们可以编写一个特殊的类来实现所有api的功能,不需要每个api都编写函数。使用的效果类似于:
    • vultr = Vultr(‘api_key’)
    • status_code, resp = vultr.snapshot.list()
  3. 主要是用了__getattr__和eval的特性,具体请看源码。(部分源码参考自互联网,修复了部分bug)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import requests
from requests import get
import re


class __RPC:
    def __init__(self, api_key, name):
        self.api_key = api_key
        self.api_info = None
        self.name = name
        self.errors = {
            200: "Function successfully executed.",
            400: "Invalid API location. Check the URL that you are using.",
            403: "Invalid or missing API key. Check that your API key is present and matches your assigned key.",
            405: "Invalid HTTP method. Check that the method (POST|GET) matches what the documentation indicates.",
            412: "Request failed. Check the response body for a more detailed description.",
            500: "Internal server error. Try again at a later time.",
            503: "Rate limit hit. API requests are limited to an average of 2/s. Try your request again later."
        }

    def api_info_initial(self):
        res = get("https://www.vultr.com/api/")
        html = res.text
        methods = (m.group(1) for m in re.finditer(r"<td>(POST|GET)</td>", html))
        names = (m.group(1) for m in re.finditer(r"/v1/(.*?)</a>", html))
        self.api_info = dict(zip(names, methods))

    def __getattr__(self, name):
        return eval("__RPC")(self.api_key, self.name + "/" + name)

    def __call__(self, **kwargs):
        if not self.api_info:
            self.api_info_initial()
        if self.name not in self.api_info:
            raise ValueError("The API is not exists.")

        if self.api_info[self.name] == "GET":
            res = requests.get("https://api.vultr.com/v1/" + self.name, headers={"API-Key": self.api_key},
                               params=kwargs)
        elif self.api_info[self.name] == "POST":
            res = requests.post("https://api.vultr.com/v1/" + self.name, headers={"API-Key": self.api_key}, data=kwargs)

        if res.status_code == 200:
            return res.status_code, res.text.strip()
        elif res.status_code in self.errors.keys():
            return res.status_code, self.errors.get(res.status_code)
        else:
            res.raise_for_status()


class Vultr:
    def __init__(self, api_key):
        self.api_key = api_key

    def __getattr__(self, name):
        return eval("__RPC")(self.api_key, name)

发起创建快照请求,并删除超过3010个之后的快照,防止快照太多了造成vultr资源滥用,毕竟免费用的啊

注意
更新:只能创建10个快照
  1. 先获取到创建的vps对应的SUBID:/v1/server/list
1
2
3
4
5
6
7
from vultr import Vultr
vultr = Vultr("api_key")
status_code, resp = vultr.server.list()
print(status_code, resp)

# print的响应
# 200 {'15388455': {'SUBID': '15388455', ......}}
  1. 发起创建快照请求:/v1/snapshot/create。如果状态是200,表示创建成功,去网页上看看果然创建了。需要注意的是当一个快照处于pending状态时,服务被锁定,如果再创建快照,报412错误。也就是说不能同时创建多个快照。
1
2
3
4
5
6
7
8
from vultr import Vultr
vultr = Vultr("api_key")
data = {'SUBID': '15388455'}
status_code, resp = vultr.snapshot.create(**data)
print(status_code, resp)

# print的响应
# 200 {'SNAPSHOTID': '1e05b17c45fd6'}
  1. 删除超过30个之后的快照,根据时间排序
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 删除旧快照
status_code, resp = vultr.snapshot.list()  # /v1/snapshot/list
if status_code != 200:
    logger.error(u'获取快照列表失败' + str(status_code) + resp)
else:
    logger.info(u'成功获取到快照列表')
    data_list = list(json.loads(resp).values())
    data_list.sort(key=lambda x: x['date_created'])  # 默认时间排序,由近到远
    data_list_del = data_list[10:]  # 取超过30个之后的快照
    for data_del in data_list_del:
        data = {'SNAPSHOTID': data_del.get('SNAPSHOTID')}
        status_code, resp = vultr.snapshot.destroy(**data)  # /v1/snapshot/destroy
        if status_code != 200:
            logger.error(u'删除旧快照失败')
        else:
            logger.info(u'成功删除一个旧快照')
1
2
# 自动创建快照
30 18 * * * /usr/bin/python3 /home/script/vultr-snapshot.py

当创建快照失败的时候,如果能有一封邮件提醒岂不是更高潮嘛,嗯,简单,logging已经提供了邮件发送功能,照着写配置就ok啦!

虽然说快照功能是免费,但是扛不住人多呀。所以,源码就不提供了,关键部分文中都已经给出了。如果真的想要源码学习交流呢,请发邮件给我