def _handle_500_error(self, raw_response): request_id = raw_response.headers["X-Request-Id"] if raw_response.json(): message = raw_response.json()["data"] else: message = "There was no error message" raise exceptions.KazooApiError("Internal Server Error, " "Request ID was {0}" " message was {1}".format( request_id, message))
def getUser(self, accountId, kazooUserId): if accountId is None or kazooUserId is None: raise exceptions.KazooApiError( u'accountId {} and kazooUserId {} must be provided'.format( accountId, kazooUserId)) result = self.kazooCli.get_user(accountId, kazooUserId) return result
def _handle_error(self, error_data): if error_data["error"] == "400" and ("data" in error_data): raise exceptions.KazooApiBadDataError(error_data["data"]) raise exceptions.KazooApiError( "There was an error calling the kazoo api, " "Request ID was {1}" "the error was {0}".format( error_data["message"], error_data["request_id"], ))
def createEnterpriseAccount(self, enterpriseId, name): ''' Given a enterprise id and name, create an account on Kazoo enterpriseId Id of the EnterpriseAccount to be created on kazoo (unique) name Name of the EnterpriseAccount to be created on kazoo ''' logging.info(u'createEnterpriseAccount invoked with {},{}'.format( enterpriseId, name)) if enterpriseId is None or name is None: raise exceptions.KazooApiError( u'EnterpriseId {} and Name {} must be provided'.format( enterpriseId, name)) result = {} @retry(3) def _wrappedAccountCreation(result): ''' Wrap calls to account creation to allow for retries ''' result.update( self.kazooCli.create_account({ u'name': str(enterpriseId), u'enterprise_id': str(enterpriseId), u'enterprise_name': name, u'realm': u'{}.sip.sendhub.com'.format(enterpriseId) })) return ('data' in result and 'id' in result['data']) if _wrappedAccountCreation(result): logging.info( 'Created account {} successfully. Kazoo id = {}'.format( enterpriseId, result['data']['id'])) # create the no-match call flow for this account # so the global carrier stuff works self.kazooCli.create_callflow(result['data']['id'], deepcopy(NO_MATCH_CALL_FLOW)) else: logging.error( 'Unable to create account on kazoo: {}'.format(result)) raise Exception('Kazoo account creation error: {}'.format(result)) return result
def _handle_error(self, error_data): if error_data["error"] == "400" and ("data" in error_data): raise exceptions.KazooApiBadDataError(error_data["data"]) if error_data['error'] == '401': raise exceptions.KazooApiAuthenticationError('Invalid credentials') raise exceptions.KazooApiError( "There was an error calling the kazoo api," " Request ID was {1} the error was {0}".format(error_data["message"], error_data["request_id"]) )
def updateUser(self, accountId, kazooUserId, updateData): ''' Update a user on Kazoo within an given account updateData is a dictionary of optional (specific) overwrites over current user data in Kazoo ''' if accountId is None or kazooUserId is None or updateData is None: raise exceptions.KazooApiError( u'accountId {} and kazooUserId {} and updateData {} must be provided' .format(accountId, kazooUserId, updateData)) currentUserRes = self.kazooCli.get_user(accountId, kazooUserId) if currentUserRes['status'] != 'success': raise exceptions.KazooApiError( u'Failed to get user: accountId {}, kazooUserId {}'.format( accountId, kazooUserId)) userData = currentUserRes['data'] userData.update(updateData) result = self.kazooCli.update_user(accountId, kazooUserId, userData) return result
def copyMedia(self, accountId, mediaId, fromUrl): # this function doesn't fit the general model for crossbar API URLs hence why it is hand built try: c = None fh = None mediaData = wget(fromUrl, numTries=3) toUrl = '{}/accounts/{}/media/{}/raw'.format( self.kazooCli.base_url, accountId, mediaId) fh = tempfile.NamedTemporaryFile(mode='wr+b') fh.write(mediaData) fh.flush() fh.seek(0) c = pycurl.Curl() c.setopt(pycurl.URL, toUrl) c.setopt(pycurl.READFUNCTION, fh.read) c.setopt(pycurl.POST, 1) c.setopt(pycurl.HTTPHEADER, [ "Content-type: audio/mp3", "X-Auth-Token: {}".format( self.kazooCli.auth_token) ]) c.setopt(pycurl.POSTFIELDSIZE, os.path.getsize(fh.name)) response = cStringIO.StringIO() c.setopt(c.WRITEFUNCTION, response.write) logging.info(u'Uploading file %s to url %s' % (fh.name, toUrl)) c.perform() returnCode = c.getinfo(pycurl.HTTP_CODE) logging.info("File upload %s Http %d Response %s" % (fh.name, returnCode, response.getvalue())) if returnCode != 200: raise exceptions.KazooApiError( 'Failed upload media, return code %d' % returnCode) finally: if c is not None: c.close() if fh is not None: fh.close()
def createUser(self, accountId, name, userId, password, enterpriseId, sipUsername, sipPassword, softPhoneNumber=None, cellPhoneNumbers=[], email=None): ''' Create a user on Kazoo within an given enterprise or within the general sendhub enterprise accountId: Account on kazoo which this user will be created under name: ShUser name userId: Id of the user password: Password to set on kazoo enterpriseId: The id of the enterprise account. The account must already exist on kazoo. sipUsername: SIP device username for the web device sipPassword: SIP password for the web device softPhoneNumber: Voip number too add for this account cellPhoneNumbers: Cell phone numbers to add for this account email: Email address for this account (will be set to a unique-bogus email if not specified as kazoo requires it) ''' logging.info(u'createUser invoked with {},{},{},{},{},{},{},{}'.format( accountId, name, userId, password, enterpriseId, sipUsername, softPhoneNumber, cellPhoneNumbers)) userDetails = { 'id': None, 'first_name': None, 'username': None, 'voicemailId': None, 'softphoneId': None, 'cellphoneIds': [], 'callFlowId': None, 'autoAttendantMenuId': None, 'temporalRuleId': None } shortSoftPhoneNumber = None if name is None or userId is None or password is None: raise exceptions.KazooApiError( u'userId () and Name () must be provided'.format(userId, name)) createUserResult = None try: userSettings = { u'first_name': name, u'last_name': 'SH', u'username': str(userId), u'password': password, u'enterprise_id': str(enterpriseId), u'email': u'{}@no-reply.sendhub.com'.format(email) if email is None else email, u'vm_to_email_enabled': False, } if softPhoneNumber is not None: shortSoftPhoneNumber = softPhoneNumber[ 2:] if softPhoneNumber.startswith( "+1") else softPhoneNumber callerId = { u'caller_id': { u'internal': { u'name': name, u'number': shortSoftPhoneNumber }, u'external': { u'name': name, u'number': shortSoftPhoneNumber } } } userSettings.update(callerId) createUserResult = self.kazooCli.create_user( accountId, userSettings) if createUserResult['status'] == 'success': userDetails['id'] = createUserResult['data']['id'] userDetails['name'] = createUserResult['data']['first_name'] userDetails['username'] = createUserResult['data']['username'] userDetails['enterpriseId'] = createUserResult['data'][ 'enterprise_id'] callFlow = deepcopy(DEFAULT_KAZOO_CALL_FLOW) softPhoneDeviceResult = None if softPhoneNumber is not None: createNumberResult = self.createPhoneNumber( accountId, shortSoftPhoneNumber) if 'data' not in createNumberResult or 'id' not in createNumberResult[ 'data']: raise exceptions.KazooApiError( u'Unable to create phone number: {}'.format( shortSoftPhoneNumber)) callFlow['numbers'].append(softPhoneNumber) softPhoneDeviceResult = self.createDevice( type=u'softphone', accountId=accountId, userId=userId, ownerId=userDetails['id'], number=shortSoftPhoneNumber, username=sipUsername, password=sipPassword) userDetails['softphoneId'] = softPhoneDeviceResult['data'][ 'id'] if softPhoneDeviceResult is not None else None callFlow['numbers'].append(str(userId)) callFlow['flow']['data']['id'] = str(userDetails['id']) cellPhoneResults = [] for number in cellPhoneNumbers: if number is not None: shortNumber = number[2:] if number.startswith( "+1") else number cellPhoneResult = self.createDevice( type=u'cellphone', accountId=accountId, userId=userId, ownerId=userDetails['id'], number=shortNumber) if cellPhoneResult is not None: cellPhoneResults.append(cellPhoneResult) userDetails['cellphoneIds'] = [{ 'id': cellPhoneResult['data']['id'], 'number': '+1{}'.format( cellPhoneResult['data']['call_forward']['number']) } for cellPhoneResult in cellPhoneResults] # the following requires that the schema be changed on kazoo. # so if this fails, then check vmBoxObj = self.kazooCli.create_voicemail_box( accountId, { 'mailbox': str(userId), 'check_if_owner': True, 'require_pin': False, 'name': str(userId), 'check_if_owner': True, 'delete_after_notify': True, 'owner_id': str(userDetails['id']) }) userDetails['voicemailId'] = vmBoxObj['data']['id'] callFlow['flow']['children']['_']['data']['id'] = userDetails[ 'voicemailId'] callFlowResult = self.kazooCli.create_callflow( accountId, callFlow) userDetails['callFlowId'] = callFlowResult['data']['id'] autoAttendantMenuResult = self.kazooCli.create_menu( accountId, { 'name': str(userId), 'retries': 3, 'timeout': '10000', 'max_extension_length': '1' }) userDetails['autoAttendantMenuId'] = autoAttendantMenuResult[ 'data']['id'] temporalRuleResult = self.kazooCli.create_temporal_rule( accountId, { 'name': str(userId), 'time_window_start': 0, 'time_window_stop': 86400, 'wdays': [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ], 'name': '{}'.format(str(userId)), 'cycle': 'weekly', 'start_date': 62586115200, 'ordinal': 'every', 'interval': 1 }) userDetails['temporalRuleId'] = temporalRuleResult['data'][ 'id'] except Exception as e: logging.error(u'Unable to create user on Kazoo: {}'.format(e)) import traceback traceback.print_exc(e) # if we couldn't create the user then try to delete them so # we can try again if createUserResult is not None and createUserResult[ 'status'] == 'success': logging.error(u'Deleting partially created user') self.deleteUser( accountId, userDetails['id'], shortSoftPhoneNumber, userDetails['cellphoneIds'].extend([ userDetails['softphoneId'] ]), userDetails['voicemailId'], userDetails['callFlowId'], userDetails['autoAttendantMenuId'], userDetails['temporalRuleId']) raise return userDetails