1# Licensed to the Apache Software Foundation (ASF) under one or more 2# contributor license agreements. See the NOTICE file distributed with 3# this work for additional information regarding copyright ownership. 4# The ASF licenses this file to You under the Apache License, Version 2.0 5# (the "License"); you may not use this file except in compliance with 6# the License. You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15import re 16 17from libcloud.common.base import ConnectionUserAndKey 18from libcloud.common.base import Response 19from libcloud.common.types import ProviderError 20 21 22OK_CODES = ['200', '211', '212', '213'] 23ERROR_CODES = ['401', '403', '405', '406', '407', '408', '409', '410', '411', 24 '412', '413', '414', '450', '451'] 25 26 27class WorldWideDNSException(ProviderError): 28 def __init__(self, value, http_code, code, driver=None): 29 self.code = code 30 super(WorldWideDNSException, self).__init__(value, http_code, driver) 31 32 33class SuspendedAccount(WorldWideDNSException): 34 def __init__(self, http_code, driver=None): 35 value = "Login ID you supplied is SUSPENDED, you need to renew" + \ 36 " your account" 37 super(SuspendedAccount, self).__init__(value, http_code, 401, 38 driver) 39 40 41class LoginOrPasswordNotMatch(WorldWideDNSException): 42 def __init__(self, http_code, driver=None): 43 value = "Login ID and/or Password you supplied is not on file or" + \ 44 " does not match" 45 super(LoginOrPasswordNotMatch, self).__init__(value, http_code, 403, 46 driver) 47 48 49class NonExistentDomain(WorldWideDNSException): 50 def __init__(self, http_code, driver=None): 51 value = "Domain name supplied is not in your account" 52 super(NonExistentDomain, self).__init__(value, http_code, 405, 53 driver) 54 55 56class CouldntRemoveDomain(WorldWideDNSException): 57 def __init__(self, http_code, driver=None): 58 value = "Error occured removing domain from name server, try again" 59 super(CouldntRemoveDomain, self).__init__(value, http_code, 406, 60 driver) 61 62 63class LimitExceeded(WorldWideDNSException): 64 def __init__(self, http_code, driver=None): 65 value = "Your limit was exceeded, you need to upgrade your account" 66 super(LimitExceeded, self).__init__(value, http_code, 407, 67 driver) 68 69 70class ExistentDomain(WorldWideDNSException): 71 def __init__(self, http_code, driver=None): 72 value = "Domain already exists on our servers" 73 super(ExistentDomain, self).__init__(value, http_code, 408, 74 driver) 75 76 77class DomainBanned(WorldWideDNSException): 78 def __init__(self, http_code, driver=None): 79 value = "Domain is listed in DNSBL and is banned from our servers" 80 super(DomainBanned, self).__init__(value, http_code, 409, 81 driver) 82 83 84class InvalidDomainName(WorldWideDNSException): 85 def __init__(self, http_code, driver=None): 86 value = "Invalid domain name" 87 super(InvalidDomainName, self).__init__(value, http_code, 410, 88 driver) 89 90 91class ErrorOnReloadInNameServer(WorldWideDNSException): 92 def __init__(self, server, http_code, driver=None): 93 if server == 1: 94 value = "Name server #1 kicked an error on reload, contact support" 95 code = 411 96 elif server == 2: 97 value = "Name server #2 kicked an error on reload, contact support" 98 code = 412 99 elif server == 3: 100 value = "Name server #3 kicked an error on reload, contact support" 101 code = 413 102 super(ErrorOnReloadInNameServer, self).__init__(value, http_code, code, 103 driver) 104 105 106class NewUserNotValid(WorldWideDNSException): 107 def __init__(self, http_code, driver=None): 108 value = "New userid is not valid" 109 super(NewUserNotValid, self).__init__(value, http_code, 414, 110 driver) 111 112 113class CouldntReachNameServer(WorldWideDNSException): 114 def __init__(self, http_code, driver=None): 115 value = "Couldn't reach the name server, try again later" 116 super(CouldntReachNameServer, self).__init__(value, http_code, 450, 117 driver) 118 119 120class NoZoneFile(WorldWideDNSException): 121 def __init__(self, http_code, driver=None): 122 value = "No zone file in the name server queried" 123 super(NoZoneFile, self).__init__(value, http_code, 451, 124 driver) 125 126 127ERROR_CODE_TO_EXCEPTION_CLS = { 128 '401': SuspendedAccount, 129 '403': LoginOrPasswordNotMatch, 130 '405': NonExistentDomain, 131 '406': CouldntRemoveDomain, 132 '407': LimitExceeded, 133 '408': ExistentDomain, 134 '409': DomainBanned, 135 '410': InvalidDomainName, 136 '411': ErrorOnReloadInNameServer, 137 '412': ErrorOnReloadInNameServer, 138 '413': ErrorOnReloadInNameServer, 139 '414': NewUserNotValid, 140 '450': CouldntReachNameServer, 141 '451': NoZoneFile, 142} 143 144 145class WorldWideDNSResponse(Response): 146 147 def parse_body(self): 148 """ 149 Parse response body. 150 151 :return: Parsed body. 152 :rtype: ``str`` 153 """ 154 if self._code_response(self.body): 155 codes = re.split('\r?\n', self.body) 156 for code in codes: 157 if code in OK_CODES: 158 continue 159 elif code in ERROR_CODES: 160 exception = ERROR_CODE_TO_EXCEPTION_CLS.get(code) 161 if code in ['411', '412', '413']: 162 server = int(code[2]) 163 raise exception(server, self.status) 164 raise exception(self.status) 165 return self.body 166 167 def _code_response(self, body): 168 """ 169 Checks if the response body contains code status. 170 171 :rtype: ``bool`` 172 """ 173 available_response_codes = OK_CODES + ERROR_CODES 174 codes = re.split('\r?\n', body) 175 if codes[0] in available_response_codes: 176 return True 177 return False 178 179 180class WorldWideDNSConnection(ConnectionUserAndKey): 181 host = 'www.worldwidedns.net' 182 responseCls = WorldWideDNSResponse 183 184 def add_default_params(self, params): 185 """ 186 Add parameters that are necessary for every request 187 188 This method adds ``NAME`` and ``PASSWORD`` to 189 the request. 190 """ 191 params["NAME"] = self.user_id 192 params["PASSWORD"] = self.key 193 194 reseller_id = getattr(self, 'reseller_id', None) 195 if reseller_id: 196 params["ID"] = reseller_id 197 198 return params 199