<s> import copy <EOL> from libcloud . utils . py3 import httplib <EOL> from libcloud . common . openstack import OpenStackDriverMixin <EOL> from libcloud . common . base import PollingConnection <EOL> from libcloud . common . exceptions import BaseHTTPError <EOL> from libcloud . common . types import LibcloudError <EOL> from libcloud . utils . misc import merge_valid_keys , get_new_obj <EOL> from libcloud . common . rackspace import AUTH_URL <EOL> from libcloud . compute . drivers . openstack import OpenStack_1_1_Connection <EOL> from libcloud . compute . drivers . openstack import OpenStack_1_1_Response <EOL> from libcloud . dns . types import Provider , RecordType <EOL> from libcloud . dns . types import ZoneDoesNotExistError , RecordDoesNotExistError <EOL> from libcloud . dns . base import DNSDriver , Zone , Record <EOL> __all__ = [ <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' <EOL> ] <EOL> VALID_ZONE_EXTRA_PARAMS = [ '<STR_LIT:email>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> VALID_RECORD_EXTRA_PARAMS = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' ] <EOL> class RackspaceDNSResponse ( OpenStack_1_1_Response ) : <EOL> """<STR_LIT>""" <EOL> def parse_error ( self ) : <EOL> status = int ( self . status ) <EOL> context = self . connection . context <EOL> body = self . parse_body ( ) <EOL> if status == httplib . NOT_FOUND : <EOL> if context [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> raise ZoneDoesNotExistError ( value = '<STR_LIT>' , driver = self , <EOL> zone_id = context [ '<STR_LIT:id>' ] ) <EOL> elif context [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> raise RecordDoesNotExistError ( value = '<STR_LIT>' , driver = self , <EOL> record_id = context [ '<STR_LIT:id>' ] ) <EOL> if body : <EOL> if '<STR_LIT:code>' and '<STR_LIT:message>' in body : <EOL> err = '<STR_LIT>' % ( body [ '<STR_LIT:code>' ] , body [ '<STR_LIT:message>' ] , <EOL> body [ '<STR_LIT>' ] ) <EOL> return err <EOL> elif '<STR_LIT>' in body : <EOL> errors = [ m for m in body [ '<STR_LIT>' ] [ '<STR_LIT>' ] ] <EOL> err = '<STR_LIT>' % '<STR_LIT:U+002CU+0020>' . join ( errors ) <EOL> return err <EOL> raise LibcloudError ( '<STR_LIT>' % ( status ) ) <EOL> class RackspaceDNSConnection ( OpenStack_1_1_Connection , PollingConnection ) : <EOL> """<STR_LIT>""" <EOL> responseCls = RackspaceDNSResponse <EOL> XML_NAMESPACE = None <EOL> poll_interval = <NUM_LIT> <EOL> timeout = <NUM_LIT:30> <EOL> auth_url = AUTH_URL <EOL> _auth_version = '<STR_LIT>' <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> self . region = kwargs . pop ( '<STR_LIT>' , None ) <EOL> super ( RackspaceDNSConnection , self ) . __init__ ( * args , ** kwargs ) <EOL> def get_poll_request_kwargs ( self , response , context , request_kwargs ) : <EOL> job_id = response . object [ '<STR_LIT>' ] <EOL> kwargs = { '<STR_LIT:action>' : '<STR_LIT>' % ( job_id ) , <EOL> '<STR_LIT>' : { '<STR_LIT>' : True } } <EOL> return kwargs <EOL> def has_completed ( self , response ) : <EOL> status = response . object [ '<STR_LIT:status>' ] <EOL> if status == '<STR_LIT>' : <EOL> data = response . object [ '<STR_LIT:error>' ] <EOL> if '<STR_LIT:code>' and '<STR_LIT:message>' in data : <EOL> message = '<STR_LIT>' % ( data [ '<STR_LIT:code>' ] , data [ '<STR_LIT:message>' ] , <EOL> data [ '<STR_LIT>' ] ) <EOL> else : <EOL> message = data [ '<STR_LIT:message>' ] <EOL> raise LibcloudError ( message , <EOL> driver = self . driver ) <EOL> return status == '<STR_LIT>' <EOL> def get_endpoint ( self ) : <EOL> if '<STR_LIT>' in self . _auth_version : <EOL> ep = self . service_catalog . get_endpoint ( name = '<STR_LIT>' , <EOL> service_type = '<STR_LIT>' , <EOL> region = None ) <EOL> else : <EOL> raise LibcloudError ( "<STR_LIT>" % <EOL> ( self . _auth_version ) ) <EOL> public_url = ep . url <EOL> if self . region == '<STR_LIT>' : <EOL> public_url = public_url . replace ( '<STR_LIT>' , <EOL> '<STR_LIT>' ) <EOL> if self . region == '<STR_LIT>' : <EOL> public_url = public_url . replace ( '<STR_LIT>' , <EOL> '<STR_LIT>' ) <EOL> return public_url <EOL> class RackspacePTRRecord ( object ) : <EOL> def __init__ ( self , id , ip , domain , driver , extra = None ) : <EOL> self . id = str ( id ) if id else None <EOL> self . ip = ip <EOL> self . type = RecordType . PTR <EOL> self . domain = domain <EOL> self . driver = driver <EOL> self . extra = extra or { } <EOL> def update ( self , domain , extra = None ) : <EOL> return self . driver . ex_update_ptr_record ( record = self , domain = domain , <EOL> extra = extra ) <EOL> def delete ( self ) : <EOL> return self . driver . ex_delete_ptr_record ( record = self ) <EOL> def __repr__ ( self ) : <EOL> return ( '<STR_LIT>' % <EOL> ( self . __class__ . __name__ , self . ip , <EOL> self . domain , self . driver . name ) ) <EOL> class RackspaceDNSDriver ( DNSDriver , OpenStackDriverMixin ) : <EOL> name = '<STR_LIT>' <EOL> website = '<STR_LIT>' <EOL> type = Provider . RACKSPACE <EOL> connectionCls = RackspaceDNSConnection <EOL> def __init__ ( self , key , secret = None , secure = True , host = None , port = None , <EOL> region = '<STR_LIT>' , ** kwargs ) : <EOL> valid_regions = self . list_regions ( ) <EOL> if region not in valid_regions : <EOL> raise ValueError ( '<STR_LIT>' % ( region ) ) <EOL> OpenStackDriverMixin . __init__ ( self , ** kwargs ) <EOL> super ( RackspaceDNSDriver , self ) . __init__ ( key = key , secret = secret , <EOL> host = host , port = port , <EOL> region = region ) <EOL> RECORD_TYPE_MAP = { <EOL> RecordType . A : '<STR_LIT:A>' , <EOL> RecordType . AAAA : '<STR_LIT>' , <EOL> RecordType . CNAME : '<STR_LIT>' , <EOL> RecordType . MX : '<STR_LIT>' , <EOL> RecordType . NS : '<STR_LIT>' , <EOL> RecordType . PTR : '<STR_LIT>' , <EOL> RecordType . SRV : '<STR_LIT>' , <EOL> RecordType . TXT : '<STR_LIT>' , <EOL> } <EOL> @ classmethod <EOL> def list_regions ( cls ) : <EOL> return [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> def iterate_zones ( self ) : <EOL> offset = <NUM_LIT:0> <EOL> limit = <NUM_LIT:100> <EOL> while True : <EOL> params = { <EOL> '<STR_LIT>' : limit , <EOL> '<STR_LIT>' : offset , <EOL> } <EOL> response = self . connection . request ( <EOL> action = '<STR_LIT>' , params = params ) . object <EOL> zones_list = response [ '<STR_LIT>' ] <EOL> for item in zones_list : <EOL> yield self . _to_zone ( item ) <EOL> if _rackspace_result_has_more ( response , len ( zones_list ) , limit ) : <EOL> offset += limit <EOL> else : <EOL> break <EOL> def iterate_records ( self , zone ) : <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : zone . id } ) <EOL> offset = <NUM_LIT:0> <EOL> limit = <NUM_LIT:100> <EOL> while True : <EOL> params = { <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : limit , <EOL> '<STR_LIT>' : offset , <EOL> } <EOL> response = self . connection . request ( <EOL> action = '<STR_LIT>' % ( zone . id ) , params = params ) . object <EOL> records_list = response [ '<STR_LIT>' ] <EOL> records = records_list [ '<STR_LIT>' ] <EOL> for item in records : <EOL> record = self . _to_record ( data = item , zone = zone ) <EOL> yield record <EOL> if _rackspace_result_has_more ( records_list , len ( records ) , limit ) : <EOL> offset += limit <EOL> else : <EOL> break <EOL> def get_zone ( self , zone_id ) : <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : zone_id } ) <EOL> response = self . connection . request ( action = '<STR_LIT>' % ( zone_id ) ) <EOL> zone = self . _to_zone ( data = response . object ) <EOL> return zone <EOL> def get_record ( self , zone_id , record_id ) : <EOL> zone = self . get_zone ( zone_id = zone_id ) <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : record_id } ) <EOL> response = self . connection . request ( action = '<STR_LIT>' % <EOL> ( zone_id , record_id ) ) . object <EOL> record = self . _to_record ( data = response , zone = zone ) <EOL> return record <EOL> def create_zone ( self , domain , type = '<STR_LIT>' , ttl = None , extra = None ) : <EOL> extra = extra if extra else { } <EOL> if '<STR_LIT:email>' not in extra : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> payload = { '<STR_LIT:name>' : domain , '<STR_LIT>' : extra [ '<STR_LIT:email>' ] , <EOL> '<STR_LIT>' : { '<STR_LIT>' : [ ] } } <EOL> if ttl : <EOL> payload [ '<STR_LIT>' ] = ttl <EOL> if '<STR_LIT>' in extra : <EOL> payload [ '<STR_LIT>' ] = extra [ '<STR_LIT>' ] <EOL> data = { '<STR_LIT>' : [ payload ] } <EOL> response = self . connection . async_request ( action = '<STR_LIT>' , <EOL> method = '<STR_LIT:POST>' , data = data ) <EOL> zone = self . _to_zone ( data = response . object [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ <NUM_LIT:0> ] ) <EOL> return zone <EOL> def update_zone ( self , zone , domain = None , type = None , ttl = None , extra = None ) : <EOL> extra = extra if extra else { } <EOL> if domain : <EOL> raise LibcloudError ( '<STR_LIT>' , driver = self ) <EOL> data = { } <EOL> if ttl : <EOL> data [ '<STR_LIT>' ] = int ( ttl ) <EOL> if '<STR_LIT:email>' in extra : <EOL> data [ '<STR_LIT>' ] = extra [ '<STR_LIT:email>' ] <EOL> if '<STR_LIT>' in extra : <EOL> data [ '<STR_LIT>' ] = extra [ '<STR_LIT>' ] <EOL> type = type if type else zone . type <EOL> ttl = ttl if ttl else zone . ttl <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : zone . id } ) <EOL> self . connection . async_request ( action = '<STR_LIT>' % ( zone . id ) , <EOL> method = '<STR_LIT>' , data = data ) <EOL> merged = merge_valid_keys ( params = copy . deepcopy ( zone . extra ) , <EOL> valid_keys = VALID_ZONE_EXTRA_PARAMS , <EOL> extra = extra ) <EOL> updated_zone = get_new_obj ( obj = zone , klass = Zone , <EOL> attributes = { '<STR_LIT:type>' : type , <EOL> '<STR_LIT>' : ttl , <EOL> '<STR_LIT>' : merged } ) <EOL> return updated_zone <EOL> def create_record ( self , name , zone , type , data , extra = None ) : <EOL> extra = extra if extra else { } <EOL> name = self . _to_full_record_name ( domain = zone . domain , name = name ) <EOL> data = { '<STR_LIT:name>' : name , '<STR_LIT:type>' : self . RECORD_TYPE_MAP [ type ] , <EOL> '<STR_LIT:data>' : data } <EOL> if '<STR_LIT>' in extra : <EOL> data [ '<STR_LIT>' ] = int ( extra [ '<STR_LIT>' ] ) <EOL> if '<STR_LIT>' in extra : <EOL> data [ '<STR_LIT>' ] = int ( extra [ '<STR_LIT>' ] ) <EOL> payload = { '<STR_LIT>' : [ data ] } <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : zone . id } ) <EOL> response = self . connection . async_request ( action = '<STR_LIT>' <EOL> % ( zone . id ) , data = payload , <EOL> method = '<STR_LIT:POST>' ) . object <EOL> record = self . _to_record ( data = response [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ <NUM_LIT:0> ] , <EOL> zone = zone ) <EOL> return record <EOL> def update_record ( self , record , name = None , type = None , data = None , <EOL> extra = None ) : <EOL> extra = extra if extra else { } <EOL> name = self . _to_full_record_name ( domain = record . zone . domain , <EOL> name = record . name ) <EOL> payload = { '<STR_LIT:name>' : name } <EOL> if data : <EOL> payload [ '<STR_LIT:data>' ] = data <EOL> if '<STR_LIT>' in extra : <EOL> payload [ '<STR_LIT>' ] = extra [ '<STR_LIT>' ] <EOL> if '<STR_LIT>' in extra : <EOL> payload [ '<STR_LIT>' ] = extra [ '<STR_LIT>' ] <EOL> type = type if type is not None else record . type <EOL> data = data if data else record . data <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : record . id } ) <EOL> self . connection . async_request ( action = '<STR_LIT>' % <EOL> ( record . zone . id , record . id ) , <EOL> method = '<STR_LIT>' , data = payload ) <EOL> merged = merge_valid_keys ( params = copy . deepcopy ( record . extra ) , <EOL> valid_keys = VALID_RECORD_EXTRA_PARAMS , <EOL> extra = extra ) <EOL> updated_record = get_new_obj ( obj = record , klass = Record , <EOL> attributes = { '<STR_LIT:type>' : type , <EOL> '<STR_LIT:data>' : data , <EOL> '<STR_LIT>' : self , <EOL> '<STR_LIT>' : merged } ) <EOL> return updated_record <EOL> def delete_zone ( self , zone ) : <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : zone . id } ) <EOL> self . connection . async_request ( action = '<STR_LIT>' % ( zone . id ) , <EOL> method = '<STR_LIT>' ) <EOL> return True <EOL> def delete_record ( self , record ) : <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : record . id } ) <EOL> self . connection . async_request ( action = '<STR_LIT>' % <EOL> ( record . zone . id , record . id ) , <EOL> method = '<STR_LIT>' ) <EOL> return True <EOL> def ex_iterate_ptr_records ( self , device ) : <EOL> """<STR_LIT>""" <EOL> _check_ptr_extra_fields ( device ) <EOL> params = { '<STR_LIT>' : device . extra [ '<STR_LIT>' ] } <EOL> service_name = device . extra [ '<STR_LIT>' ] <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' } ) <EOL> try : <EOL> response = self . connection . request ( <EOL> action = '<STR_LIT>' % ( service_name ) , params = params ) . object <EOL> records = response [ '<STR_LIT>' ] <EOL> link = dict ( rel = service_name , ** params ) <EOL> for item in records : <EOL> record = self . _to_ptr_record ( data = item , link = link ) <EOL> yield record <EOL> except BaseHTTPError as exc : <EOL> if exc . code == <NUM_LIT> : <EOL> return <EOL> raise <EOL> def ex_get_ptr_record ( self , service_name , record_id ) : <EOL> """<STR_LIT>""" <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : record_id } ) <EOL> response = self . connection . request ( <EOL> action = '<STR_LIT>' % ( service_name , record_id ) ) . object <EOL> item = next ( iter ( response [ '<STR_LIT>' ] [ '<STR_LIT>' ] ) ) <EOL> return self . _to_ptr_record ( data = item , link = response [ '<STR_LIT>' ] ) <EOL> def ex_create_ptr_record ( self , device , ip , domain , extra = None ) : <EOL> """<STR_LIT>""" <EOL> _check_ptr_extra_fields ( device ) <EOL> if extra is None : <EOL> extra = { } <EOL> data = { <EOL> "<STR_LIT:name>" : domain , <EOL> "<STR_LIT:type>" : RecordType . PTR , <EOL> "<STR_LIT:data>" : ip <EOL> } <EOL> if '<STR_LIT>' in extra : <EOL> data [ '<STR_LIT>' ] = extra [ '<STR_LIT>' ] <EOL> payload = { <EOL> "<STR_LIT>" : { <EOL> "<STR_LIT>" : [ data ] <EOL> } , <EOL> "<STR_LIT>" : { <EOL> "<STR_LIT:content>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : device . extra [ '<STR_LIT>' ] , <EOL> "<STR_LIT>" : device . extra [ '<STR_LIT>' ] , <EOL> } <EOL> } <EOL> response = self . connection . async_request ( <EOL> action = '<STR_LIT>' , method = '<STR_LIT:POST>' , data = payload ) . object <EOL> item = next ( iter ( response [ '<STR_LIT>' ] [ '<STR_LIT>' ] ) ) <EOL> return self . _to_ptr_record ( data = item , link = payload [ '<STR_LIT>' ] ) <EOL> def ex_update_ptr_record ( self , record , domain = None , extra = None ) : <EOL> """<STR_LIT>""" <EOL> if domain is not None and domain == record . domain : <EOL> domain = None <EOL> if extra is not None : <EOL> extra = dict ( extra ) <EOL> for key in extra : <EOL> if key in record . extra and record . extra [ key ] == extra [ key ] : <EOL> del extra [ key ] <EOL> if domain is None and not extra : <EOL> return record <EOL> _check_ptr_extra_fields ( record ) <EOL> ip = record . ip <EOL> self . ex_delete_ptr_record ( record ) <EOL> return self . ex_create_ptr_record ( record , ip , domain , extra = extra ) <EOL> def ex_delete_ptr_record ( self , record ) : <EOL> """<STR_LIT>""" <EOL> _check_ptr_extra_fields ( record ) <EOL> self . connection . set_context ( { '<STR_LIT>' : '<STR_LIT>' , '<STR_LIT:id>' : record . id } ) <EOL> self . connection . async_request ( <EOL> action = '<STR_LIT>' % ( record . extra [ '<STR_LIT>' ] ) , <EOL> method = '<STR_LIT>' , <EOL> params = { '<STR_LIT>' : record . extra [ '<STR_LIT>' ] , '<STR_LIT>' : record . ip } , <EOL> ) <EOL> return True <EOL> def _to_zone ( self , data ) : <EOL> id = data [ '<STR_LIT:id>' ] <EOL> domain = data [ '<STR_LIT:name>' ] <EOL> type = '<STR_LIT>' <EOL> ttl = data . get ( '<STR_LIT>' , <NUM_LIT:0> ) <EOL> extra = { } <EOL> if '<STR_LIT>' in data : <EOL> extra [ '<STR_LIT:email>' ] = data [ '<STR_LIT>' ] <EOL> if '<STR_LIT>' in data : <EOL> extra [ '<STR_LIT>' ] = data [ '<STR_LIT>' ] <EOL> zone = Zone ( id = str ( id ) , domain = domain , type = type , ttl = int ( ttl ) , <EOL> driver = self , extra = extra ) <EOL> return zone <EOL> def _to_record ( self , data , zone ) : <EOL> id = data [ '<STR_LIT:id>' ] <EOL> fqdn = data [ '<STR_LIT:name>' ] <EOL> name = self . _to_partial_record_name ( domain = zone . domain , name = fqdn ) <EOL> type = self . _string_to_record_type ( data [ '<STR_LIT:type>' ] ) <EOL> record_data = data [ '<STR_LIT:data>' ] <EOL> extra = { '<STR_LIT>' : fqdn } <EOL> for key in VALID_RECORD_EXTRA_PARAMS : <EOL> if key in data : <EOL> extra [ key ] = data [ key ] <EOL> record = Record ( id = str ( id ) , name = name , type = type , data = record_data , <EOL> zone = zone , driver = self , ttl = extra . get ( '<STR_LIT>' , None ) , <EOL> extra = extra ) <EOL> return record <EOL> def _to_ptr_record ( self , data , link ) : <EOL> id = data [ '<STR_LIT:id>' ] <EOL> ip = data [ '<STR_LIT:data>' ] <EOL> domain = data [ '<STR_LIT:name>' ] <EOL> extra = { '<STR_LIT>' : link [ '<STR_LIT>' ] , '<STR_LIT>' : link [ '<STR_LIT>' ] } <EOL> for key in VALID_RECORD_EXTRA_PARAMS : <EOL> if key in data : <EOL> extra [ key ] = data [ key ] <EOL> record = RackspacePTRRecord ( id = str ( id ) , ip = ip , domain = domain , <EOL> driver = self , extra = extra ) <EOL> return record <EOL> def _to_full_record_name ( self , domain , name ) : <EOL> """<STR_LIT>""" <EOL> if name : <EOL> name = '<STR_LIT>' % ( name , domain ) <EOL> else : <EOL> name = domain <EOL> return name <EOL> def _to_partial_record_name ( self , domain , name ) : <EOL> """<STR_LIT>""" <EOL> if name == domain : <EOL> return None <EOL> name = name . replace ( '<STR_LIT>' % ( domain ) , '<STR_LIT>' ) <EOL> return name <EOL> def _ex_connection_class_kwargs ( self ) : <EOL> kwargs = self . openstack_connection_kwargs ( ) <EOL> kwargs [ '<STR_LIT>' ] = self . region <EOL> return kwargs <EOL> def _rackspace_result_has_more ( response , result_length , limit ) : <EOL> if result_length < limit : <EOL> return False <EOL> for item in response . get ( '<STR_LIT>' , ( ) ) : <EOL> if item [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> return True <EOL> return False <EOL> def _check_ptr_extra_fields ( device_or_record ) : <EOL> if not ( hasattr ( device_or_record , '<STR_LIT>' ) and <EOL> isinstance ( device_or_record . extra , dict ) and <EOL> device_or_record . extra . get ( '<STR_LIT>' ) is not None and <EOL> device_or_record . extra . get ( '<STR_LIT>' ) is not None ) : <EOL> raise LibcloudError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % device_or_record ) </s>
