├── .gitignore ├── README.md ├── config.json.sample ├── kimsufi.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | config.json 2 | .idea/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Kimsufi availability 2 | 3 | Kimsufi servers are very interesting but extremely difficult to obtain. This script parses the OVH API and sends you a mail when a server is available. 4 | 5 | ## Usage 6 | 7 | Usage: 8 | kimsufi.py [options] 9 | kimsufi.py ... [options] 10 | 11 | Options: 12 | -h, --help Show this help. 13 | -v, --version Show version. 14 | -m, --mail Send a mail when a server is available. 15 | 16 | Examples: 17 | kimsufi.py 18 | kimsufi.py KS-1 KS-3 19 | kimsufi.py KS-1 --mail 20 | 21 | ## Output example 22 | 23 | $ python kimsufi.py KS-1 24 | 25 | KS-1 26 | ==== 27 | Gravelines : 1H-high 28 | Strasbourg : unavailable 29 | Roubaix : unavailable 30 | Beauharnois : unavailable 31 | 32 | ======= 33 | RESULT : 1 server is available on Kimsufi 34 | ======= 35 | 36 | ## Installation 37 | 38 | The script works on Python 2.x and 3.x. It's just a simple script, so no _setup.py_ is offer : 39 | 40 | $ git clone https://github.com/ncrocfer/kimsufi-availability.git 41 | $ cd kimsufi-availability 42 | $ pip install -r requirements.txt 43 | $ python kimsufi.py 44 | 45 | ## Mail configuration 46 | 47 | A mail can be sent with the `--mail` option. You can configure it with a `config.json` file : 48 | 49 | $ cp config.json.sample config.json 50 | $ vim config.json 51 | { 52 | "email": { 53 | "host": "...", 54 | "port": 587, 55 | "username": "...", 56 | "password": "...", 57 | "mail_from": "...", 58 | "mail_to": "..." 59 | } 60 | } 61 | 62 | ## Using Cron 63 | 64 | You can create a cron job to send you a mail periodically. For example : 65 | 66 | * * * * * python kimsufi.py KS-1 --mail 67 | 68 | ## License 69 | 70 | This script is under the [Beerware](http://en.wikipedia.org/wiki/Beerware) license. 71 | -------------------------------------------------------------------------------- /config.json.sample: -------------------------------------------------------------------------------- 1 | { 2 | "email": { 3 | "host": "smtp.mailgun.org", 4 | "port": 587, 5 | "username": "", 6 | "password": "", 7 | "mail_from": "", 8 | "mail_to": "" 9 | } 10 | } -------------------------------------------------------------------------------- /kimsufi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Find the Kimsufi servers availability. 6 | 7 | Usage: 8 | kimsufi.py [options] 9 | kimsufi.py ... [options] 10 | 11 | Options: 12 | -h, --help Show this help. 13 | -v, --version Show version. 14 | -m, --mail Sends a mail when a server is available. 15 | 16 | Examples: 17 | kimsufi.py 18 | kimsufi.py KS-1 KS-3 19 | kimsufi.py KS-1 --mail 20 | """ 21 | 22 | import sys 23 | import smtplib 24 | 25 | import requests 26 | import json 27 | import os 28 | 29 | from docopt import docopt 30 | 31 | VERSION = "1.0" 32 | 33 | API_URL = "https://ws.ovh.com/dedicated/r2/ws.dispatcher/getAvailability2" 34 | REFERENCES = { 35 | "150sk10": "KS-1", 36 | "150sk20": "KS-2", 37 | "150sk21": "KS-2", 38 | "150sk22": "KS-2 SSD", 39 | "150sk30": "KS-3", 40 | "150sk31": "KS-3", 41 | "150sk40": "KS-4", 42 | "150sk41": "KS-4", 43 | "150sk42": "KS-4", 44 | "150sk50": "KS-5", 45 | "150sk60": "KS-6", 46 | 47 | "141game1": "GAME-1", 48 | "141game2": "GAME-2", 49 | "141game3": "GAME-3", 50 | 51 | "142sys4": "SYS-IP-1", 52 | "142sys5": "SYS-IP-2", 53 | "142sys8": "SYS-IP-4", 54 | "142sys6": "SYS-IP-5", 55 | "142sys10": "SYS-IP-5S", 56 | "142sys7": "SYS-IP-6", 57 | "142sys9": "SYS-IP-6S", 58 | 59 | "143sys13": "E3-SSD-1", 60 | "143sys10": "E3-SSD-2", 61 | "143sys11": "E3-SSD-3", 62 | "143sys12": "E3-SSD-4", 63 | 64 | "143sys4": "E3-SAT-1", 65 | "143sys1": "E3-SAT-2", 66 | "143sys2": "E3-SAT-3", 67 | "143sys3": "E3-SAT-4", 68 | 69 | "141bk1": "BK-8T", 70 | "141bk2": "BK-24T" 71 | } 72 | 73 | ZONES = {'gra': 'Gravelines', 74 | 'sbg': 'Strasbourg', 75 | 'rbx': 'Roubaix', 76 | 'bhs': 'Beauharnois'} 77 | 78 | CURRENT_PATH = os.path.dirname(__file__) 79 | 80 | 81 | def get_zone_name(zone): 82 | # rbx-hz to rbx 83 | zone = zone.split('-')[0] 84 | if zone in ZONES: 85 | return ZONES[zone] 86 | else: 87 | return zone 88 | 89 | 90 | def get_servers(models): 91 | """Get the servers from the OVH API.""" 92 | 93 | r = requests.get(API_URL) 94 | response = r.json()['answer']['availability'] 95 | 96 | search = REFERENCES 97 | if models: 98 | search = {k: v for k, v in REFERENCES.items() if v in models} 99 | 100 | return [k for k in response if any(r == k['reference'] for r in search)] 101 | 102 | 103 | def get_ref(name): 104 | """Return the reference based on the server model.""" 105 | 106 | return list(REFERENCES.keys())[list(REFERENCES.values()).index(name)] 107 | 108 | 109 | def send_mail(output, total): 110 | try: 111 | with open(os.path.join(CURRENT_PATH, 'config.json')) as data: 112 | config = json.load(data) 113 | mail_host = config['email']['host'] 114 | mail_port = config['email']['port'] 115 | mail_username = config['email']['username'] 116 | mail_password = config['email']['password'] 117 | mail_from = config['email']['mail_from'] 118 | mail_to = config['email']['mail_to'] 119 | 120 | except IOError: 121 | print('Rename config.json.sample to config.json and edit it') 122 | return False 123 | 124 | """Send a mail to .""" 125 | 126 | subject = "{0} server{1} {2} available on Kimsufi".format( 127 | total, 128 | "s"[total <= 1:], 129 | ["is", "are"][total > 1] 130 | ) 131 | headers = "From: {}\r\nTo: {}\r\nSubject: {}\r\n\r\n".format( 132 | mail_from, 133 | mail_to, 134 | subject 135 | ) 136 | 137 | try: 138 | server = smtplib.SMTP(mail_host, mail_port) 139 | except smtplib.socket.gaierror: 140 | return False 141 | 142 | server.ehlo() 143 | server.starttls() 144 | server.ehlo() 145 | 146 | try: 147 | server.login(mail_username, mail_password) 148 | except smtplib.SMTPAuthenticationError: 149 | print('SMPT Auth Error!') 150 | return False 151 | 152 | try: 153 | server.sendmail(mail_from, mail_to, headers + output) 154 | return True 155 | except Exception: 156 | print('Error sending email!') 157 | return False 158 | finally: 159 | server.close() 160 | 161 | 162 | if __name__ == '__main__': 163 | arguments = docopt(__doc__, version=VERSION) 164 | kim = get_servers(arguments['']) 165 | 166 | total = 0 167 | output = "" 168 | 169 | for k in kim: 170 | output += "\n{}\n".format(REFERENCES[k['reference']]) 171 | output += "{}\n".format("=" * len(REFERENCES[k['reference']])) 172 | 173 | for z in k['zones']: 174 | invalids = ['unavailable', 'unknown'] 175 | availability = z['availability'] 176 | if not availability in invalids: 177 | total += 1 178 | output += '{} : {}\n'.format(get_zone_name(z['zone']), availability) 179 | 180 | output += "\n=======\nRESULT : {0} server{1} {2} available on Kimsufi\n=======\n".format( 181 | total, 182 | "s"[total <= 1:], 183 | ["is", "are"][total > 1] 184 | ) 185 | 186 | if total != 0: 187 | if arguments['--mail']: 188 | print(output) 189 | send_mail(output, total) 190 | else: 191 | print(output) 192 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | docopt==0.6.2 2 | requests==2.4.3 3 | --------------------------------------------------------------------------------