Adds Rackspace DNS Driver

Change-Id: Id49e24364ab0aa39245fc287960451e4233569bc
This commit is contained in:
Obulpathi 2014-11-07 15:15:25 -05:00
parent 5b4361bc0b
commit b893de24de
26 changed files with 647 additions and 64 deletions

View File

@ -71,13 +71,16 @@ replication_strategy = class:SimpleStrategy, replication_factor:1
[drivers:storage:mockdb] [drivers:storage:mockdb]
database = poppy database = poppy
[drivers:dns:rackspace] [drivers:dns:rackspace]
project_id = "<operator_project_id>" project_id = "<operator_project_id>"
api_key = "<operator_api_key>" api_key = "<operator_api_key>"
use_shards = True use_shards = True
num_shards = 500 num_shards = 499
shard_prefix = "cdn_" shard_prefix = "cdn"
url = "poppycdn.net" url = "poppycdn.net"
# You email associated with DNS, for notifications
email = "your@email.com"
[drivers:provider:fastly] [drivers:provider:fastly]
apikey = "MYAPIKEY" apikey = "MYAPIKEY"

View File

@ -18,4 +18,4 @@ from poppy.dns.base import services
Driver = driver.DNSDriverBase Driver = driver.DNSDriverBase
ServiceBase = services.ServicesControllerBase ServicesBase = services.ServicesControllerBase

View File

@ -43,14 +43,29 @@ class DNSDriverBase(object):
:raises NotImplementedError :raises NotImplementedError
""" """
raise NotImplementedError raise NotImplementedError
@abc.abstractproperty @abc.abstractproperty
def dns_name(self): def dns_name(self):
"""Name of this provider.
:raises NotImplementedError
"""
raise NotImplementedError
@property
def client(self):
"""Client for this provider.
:raises NotImplementedError
"""
raise NotImplementedError raise NotImplementedError
@abc.abstractproperty @abc.abstractproperty
def service_controller(self): def services_controller(self):
"""Returns the driver's hostname controller. """Returns the driver's hostname controller.
:raises NotImplementedError :raises NotImplementedError

View File

@ -0,0 +1,62 @@
# Copyright (c) 2014 Rackspace, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import traceback
class Responder(object):
"""Responder Class."""
def __init__(self, dns_name):
self.dns = dns_name
def failed(self, msg):
"""failed.
:param msg
:returns {error, error details}
"""
return {
'error': msg,
'error_detail': traceback.format_exc()
}
def created(self, dns_details):
"""created.
:param dns_details
:returns dns_details
"""
return dns_details
def updated(self, dns_details):
"""updated.
:param dns_details
:returns dns_details
"""
return dns_details
def deleted(self, dns_details):
"""deleted.
:param dns_details
:returns dns_details
"""
return dns_details

View File

@ -18,6 +18,7 @@ import abc
import six import six
from poppy.dns.base import controller from poppy.dns.base import controller
from poppy.dns.base import responder
@six.add_metaclass(abc.ABCMeta) @six.add_metaclass(abc.ABCMeta)
@ -27,3 +28,34 @@ class ServicesControllerBase(controller.DNSControllerBase):
def __init__(self, driver): def __init__(self, driver):
super(ServicesControllerBase, self).__init__(driver) super(ServicesControllerBase, self).__init__(driver)
self.responder = responder.Responder(driver.dns_name)
def update(self, service_old, service_updates, responders):
"""update.
:param service_old: previous service state
:param service_updates: updates to service state
:param responders: responders from providers
:raises NotImplementedError
"""
raise NotImplementedError
def delete(self, provider_details):
"""delete.
:param provider_details
:raises NotImplementedError
"""
raise NotImplementedError
def create(self, responders):
"""create.
:param responders
:raises NotImplementedError
"""
raise NotImplementedError

View File

@ -24,4 +24,4 @@ Field Mappings:
from poppy.dns.default import services from poppy.dns.default import services
ServiceController = services.ServiceController ServicesController = services.ServicesController

View File

@ -23,17 +23,42 @@ LOG = logging.getLogger(__name__)
class DNSProvider(base.Driver): class DNSProvider(base.Driver):
"""Default DNS Provider."""
def __init__(self, conf): def __init__(self, conf):
super(DNSProvider, self).__init__(conf) super(DNSProvider, self).__init__(conf)
def is_alive(self): def is_alive(self):
return False """is_alive.
:return boolean
"""
return True
@property @property
def dns_name(self): def dns_name(self):
return "Default" """DNS provider name.
:return 'Default'
"""
return 'Default'
@property @property
def service_controller(self): def client(self):
return controllers.ServiceController(self) """Client to this provider.
:return None
"""
return None
@property
def services_controller(self):
"""Hook for service controller.
:return service_controller
"""
return controllers.ServicesController(self)

View File

@ -16,9 +16,64 @@
from poppy.dns import base from poppy.dns import base
class ServiceController(base.ServiceBase): class ServicesController(base.ServicesBase):
def __init__(self, driver): def __init__(self, driver):
super(ServiceController, self).__init__(driver) super(ServicesController, self).__init__(driver)
self.driver = driver self.driver = driver
def update(self, service_old, service_updates, responders):
"""Default DNS update.
:param service_old: previous service state
:param service_updates: updates to service state
:param responders: responders from providers
"""
dns_details = {}
for responder in responders:
for provider_name in responder:
if 'error' in responder[provider_name]:
continue
access_urls = []
for link in responder[provider_name]['links']:
access_url = {
'domain': link['domain'],
'provider_url': link['href'],
'operator_url': link['href']}
access_urls.append(access_url)
dns_details[provider_name] = {'access_urls': access_urls}
return self.responder.created(dns_details)
def delete(self, provider_details):
"""Default DNS delete.
:param provider_details
"""
dns_details = {}
for provider_name in provider_details:
dns_details[provider_name] = self.responder.deleted({})
return dns_details
def create(self, responders):
"""Default DNS create.
:param responders: responders from providers
"""
dns_details = {}
for responder in responders:
for provider_name in responder:
if 'error' in responder[provider_name]:
continue
access_urls = []
for link in responder[provider_name]['links']:
access_url = {
'domain': link['domain'],
'provider_url': link['href'],
'operator_url': link['href']}
access_urls.append(access_url)
dns_details[provider_name] = {'access_urls': access_urls}
return self.responder.created(dns_details)

View File

@ -24,4 +24,4 @@ Field Mappings:
from poppy.dns.designate import services from poppy.dns.designate import services
ServiceController = services.ServiceController ServicesController = services.ServicesController

View File

@ -16,9 +16,9 @@
from poppy.dns import base from poppy.dns import base
class ServiceController(base.ServiceBase): class ServicesController(base.ServicesBase):
def __init__(self, driver): def __init__(self, driver):
super(ServiceController, self).__init__(driver) super(ServicesController, self).__init__(driver)
self.driver = driver self.driver = driver

View File

@ -24,4 +24,4 @@ Field Mappings:
from poppy.dns.rackspace import services from poppy.dns.rackspace import services
ServiceController = services.ServiceController ServicesController = services.ServicesController

View File

@ -16,6 +16,7 @@
"""DNS Provider implementation.""" """DNS Provider implementation."""
from oslo.config import cfg from oslo.config import cfg
import pyrax
from poppy.dns import base from poppy.dns import base
from poppy.dns.rackspace import controllers from poppy.dns.rackspace import controllers
@ -34,6 +35,8 @@ RACKSPACE_OPTIONS = [
help='The shard prefix to use'), help='The shard prefix to use'),
cfg.StrOpt('url', default='', cfg.StrOpt('url', default='',
help='The url for customers to CNAME to'), help='The url for customers to CNAME to'),
cfg.StrOpt('email', help='The email to be provided to Rackspace DNS for'
'creating subdomains'),
] ]
RACKSPACE_GROUP = 'drivers:dns:rackspace' RACKSPACE_GROUP = 'drivers:dns:rackspace'
@ -42,17 +45,51 @@ LOG = logging.getLogger(__name__)
class DNSProvider(base.Driver): class DNSProvider(base.Driver):
"""Rackspace DNS Provider."""
def __init__(self, conf): def __init__(self, conf):
super(DNSProvider, self).__init__(conf) super(DNSProvider, self).__init__(conf)
self._conf.register_opts(RACKSPACE_OPTIONS, group=RACKSPACE_GROUP)
self.rackdns_conf = self._conf[RACKSPACE_GROUP]
pyrax.set_setting("identity_type", "rackspace")
pyrax.set_credentials(self.rackdns_conf.project_id,
self.rackdns_conf.api_key)
self.rackdns_client = pyrax.cloud_dns
def is_alive(self): def is_alive(self):
"""is_alive.
:return boolean
"""
# TODO(obulpathi): Implement health check
# and add DNS to health endpoint
return True return True
@property @property
def dns_name(self): def dns_name(self):
return "Rackspace Cloud DNS" """DNS provider name.
:return 'Rackspace Cloud DNS'
"""
return 'Rackspace Cloud DNS'
@property @property
def service_controller(self): def client(self):
return controllers.ServiceController(self) """Client to this provider.
:return client
"""
return self.rackdns_client
@property
def services_controller(self):
"""Hook for service controller.
:return service_controller
"""
return controllers.ServicesController(self)

View File

@ -13,12 +13,334 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import random
import sets
import pyrax.exceptions as exc
from poppy.dns import base from poppy.dns import base
from poppy.openstack.common import log
LOG = log.getLogger(__name__)
class ServiceController(base.ServiceBase): class ServicesController(base.ServicesBase):
def __init__(self, driver): def __init__(self, driver):
super(ServiceController, self).__init__(driver) super(ServicesController, self).__init__(driver)
self.driver = driver self.client = driver.client
def _get_subdomain(self, subdomain_name):
"""Returns a subdomain, if it does not exist, create it
:param subdomain_name
:return subdomain
"""
try:
subdomain = self.client.find(name=subdomain_name)
except exc.NotFound:
subdomain = self.client.create(
name=subdomain_name,
emailAddress=self._driver.rackdns_conf.email,
ttl=900)
return subdomain
def _create_cname_records(self, links):
"""Creates a subdomain
:param links: Access URLS from providers
:return dns_links: Map from provider access URL to DNS access URL
"""
cdn_domain_name = self._driver.rackdns_conf.url
shard_prefix = self._driver.rackdns_conf.shard_prefix
num_shards = self._driver.rackdns_conf.num_shards
# randomly select a shard
shard_id = random.randint(0, num_shards - 1)
subdomain_name = '{0}{1}.{2}'.format(shard_prefix, shard_id,
cdn_domain_name)
subdomain = self._get_subdomain(subdomain_name)
# create CNAME record for adding
cname_records = []
dns_links = {}
for link in links:
name = '{0}.{1}'.format(link, subdomain_name)
cname_record = {'type': 'CNAME',
'name': name,
'data': links[link],
'ttl': 300}
dns_links[links[link]] = name
cname_records.append(cname_record)
# add the cname records
subdomain.add_records(cname_records)
return dns_links
def _delete_cname_record(self, access_url):
"""Delete a CNAME record
:param access_url: DNS Access URL
:return error_msg: returns error message, if any
"""
# extract shard name
shard_name = access_url.split('.')[-3]
subdomain_name = '.'.join([shard_name, self._driver.rackdns_conf.url])
# get subdomain
subdomain = self.client.find(name=subdomain_name)
# search and find the CNAME record
name = access_url
record_type = 'CNAME'
records = self.client.search_records(subdomain, record_type, name)
# delete the record
# we should get one record,
# or none if it has been deleted already
if not records:
LOG.info('DNS record already deleted: {0}'.format(access_url))
elif len(records) == 1:
LOG.info('Deleting DNS records for : {0}'.format(access_url))
records[0].delete()
elif len(records) > 1:
error_msg = 'Multiple DNS records found: {0}'.format(access_url)
return error_msg
return
def create(self, responders):
"""Create CNAME record for a service.
:param responders: responders from providers
:return dns_links: Map from provider urls to DNS urls
"""
# gather the provider urls and cname them
links = {}
for responder in responders:
for provider_name in responder:
if 'error' in responder[provider_name]:
continue
for link in responder[provider_name]['links']:
if link['rel'] == 'access_url':
links[link['domain']] = link['href']
# create CNAME records
try:
dns_links = self._create_cname_records(links)
except Exception as e:
error_msg = 'Rackspace DNS Exception: {0}'.format(e)
LOG.error(error_msg)
return self.responder.failed(error_msg)
# gather the CNAMED links
dns_details = {}
for responder in responders:
for provider_name in responder:
if 'error' in responder[provider_name]:
continue
access_urls = []
for link in responder[provider_name]['links']:
if link['rel'] == 'access_url':
access_url = {
'domain': link['domain'],
'provider_url': link['href'],
'operator_url': dns_links[link['href']]}
access_urls.append(access_url)
dns_details[provider_name] = {'access_urls': access_urls}
return self.responder.created(dns_details)
def delete(self, provider_details):
"""Delete CNAME records for a service.
:param provider_details
:return dns_details: Map from provider_name to delete errors
"""
dns_details = {}
for provider_name in provider_details:
error_msg = ''
access_urls = provider_details[provider_name].access_urls
for access_url in access_urls:
try:
msg = self._delete_cname_record(access_url['operator_url'])
if msg:
error_msg = error_msg + msg
except exc.NotFound as e:
LOG.error('Can not access the subdomain. Please make sure'
' it exists and you have permissions to CDN '
'subdomain {0}'.format(e))
error_msg = (error_msg + 'Can not access subdomain . '
'Exception: {0}'.format(e))
except Exception as e:
LOG.error('Exception: {0}'.format(e))
error_msg = error_msg + 'Exception: {0}'.format(e)
# format the error or success message for this provider
if error_msg:
dns_details[provider_name] = self.responder.failed(error_msg)
else:
dns_details[provider_name] = self.responder.deleted({})
return dns_details
def _update_added_domains(self, responders, added_domains):
"""Update added domains."""
# if no domains are added, return
dns_details = {}
if not added_domains:
for responder in responders:
for provider_name in responder:
dns_details[provider_name] = {'access_urls': {}}
return dns_details
# gather the provider links for the added domains
links = {}
for responder in responders:
for provider_name in responder:
if 'error' in responder[provider_name]:
continue
for link in responder[provider_name]['links']:
domain_added = (link['rel'] == 'access_url' and
link['domain'] in added_domains)
if domain_added:
links[link['domain']] = link['href']
# create CNAME records for added domains
try:
dns_links = self._create_cname_records(links)
except Exception as e:
error_msg = 'Rackspace DNS Exception: {0}'.format(e)
LOG.error(error_msg)
return self.responder.failed(error_msg)
# gather the CNAMED links for added domains
for responder in responders:
for provider_name in responder:
if 'error' in responder[provider_name]:
continue
access_urls = {}
for link in responder[provider_name]['links']:
if link['domain'] in added_domains:
access_urls[link['href']] = dns_links[link['href']]
dns_details[provider_name] = {'access_urls': access_urls}
return dns_details
def _update_removed_domains(self, provider_details, removed_domains):
"""Update removed domains."""
# if no domains are removed, return
dns_details = {}
if not removed_domains:
for provider_name in provider_details:
dns_details[provider_name] = {'access_urls': {}}
return dns_details
# delete the records for deleted domains
for provider_name in provider_details:
error_msg = ''
provider_detail = provider_details[provider_name]
for access_url in provider_detail.access_urls:
if access_url['domain'] not in removed_domains:
continue
try:
msg = self._delete_cname_record(access_url['operator_url'])
if msg:
error_msg = error_msg + msg
except exc.NotFound as e:
LOG.error('Can not access the subdomain. Please make sure'
' it exists and you have permissions to CDN '
'subdomain {0}'.format(e))
error_msg = (error_msg + 'Can not access subdomain. '
'Exception: {0}'.format(e))
except Exception as e:
LOG.error('Exception: {0}'.format(e))
error_msg = error_msg + 'Exception: {0}'.format(e)
# format the error or success message for this provider
if error_msg:
dns_details[provider_name] = self.responder.failed(error_msg)
else:
dns_details[provider_name] = self.responder.deleted({})
return dns_details
def update(self, service_old, service_updates, responders):
"""Update CNAME records for a service.
:param service_old: previous service state
:param service_updates: updates to service state
:param responders: responders from providers
:return dns_details: Map from provider_name to update errors
"""
# get old domains
old_domains = sets.Set()
old_access_urls_map = {}
provider_details = service_old.provider_details
for provider_name in provider_details:
provider_detail = provider_details[provider_name]
access_urls = provider_detail.access_urls
old_access_urls_map[provider_name] = {'access_urls': access_urls}
for access_url in access_urls:
old_domains.add(access_url['domain'])
# get new_domains
new_domains = sets.Set()
for responder in responders:
for provider_name in responder:
links = responder[provider_name]['links']
for link in links:
new_domains.add(link['domain'])
# if domains have not been updated, return
if not service_updates.domains:
return old_access_urls_map
# if the old set of domains is the same as new set of domains, return
if old_domains == new_domains:
return old_access_urls_map
# get the list of added, removed and common domains
added_domains = new_domains.difference(old_domains)
removed_domains = old_domains.difference(new_domains)
common_domains = new_domains.intersection(old_domains)
# add new domains
dns_links = self._update_added_domains(responders, added_domains)
# remove CNAME records for deleted domains
provider_details = service_old.provider_details
self._update_removed_domains(provider_details, removed_domains)
# gather the CNAMED links and remove stale links
dns_details = {}
for responder in responders:
for provider_name in responder:
if 'error' in responder[provider_name]:
continue
provider_detail = service_old.provider_details[provider_name]
old_access_urls = provider_detail.access_urls
operator_urls = dns_links[provider_name]['access_urls']
access_urls = []
for link in responder[provider_name]['links']:
if link['domain'] in removed_domains:
continue
elif link['domain'] in added_domains:
operator_url = operator_urls[link['href']]
access_url = {
'domain': link['domain'],
'provider_url': link['href'],
'operator_url': operator_url}
access_urls.append(access_url)
elif link['domain'] in common_domains:
# iterate through old access urls and get access url
operator_url = None
for old_access_url in old_access_urls:
if old_access_url['domain'] == link['domain']:
operator_url = old_access_url['operator_url']
break
access_url = {
'domain': link['domain'],
'provider_url': link['href'],
'operator_url': operator_url}
access_urls.append(access_url)
dns_details[provider_name] = {'access_urls': access_urls}
return self.responder.updated(dns_details)

View File

@ -29,29 +29,34 @@ def service_create_worker(providers_list, service_controller,
service_obj) service_obj)
responders.append(responder) responders.append(responder)
# create dns mapping
dns = service_controller.dns_controller
dns_responder = dns.create(responders)
provider_details_dict = {} provider_details_dict = {}
for responder in responders: for responder in responders:
for provider_name in responder: for provider_name in responder:
if 'error' not in responder[provider_name]: if 'error' in responder[provider_name]:
error_info = responder[provider_name]['error_detail']
provider_details_dict[provider_name] = (
provider_details.ProviderDetail(error_info=error_info))
provider_details_dict[provider_name].status = 'failed'
elif 'error' in dns_responder[provider_name]:
error_info = dns_responder[provider_name]['error_detail']
provider_details_dict[provider_name] = (
provider_details.ProviderDetail(error_info=error_info))
provider_details_dict[provider_name].status = 'failed'
else:
access_urls = dns_responder[provider_name]['access_urls']
provider_details_dict[provider_name] = ( provider_details_dict[provider_name] = (
provider_details.ProviderDetail( provider_details.ProviderDetail(
provider_service_id=responder[provider_name]['id'], provider_service_id=responder[provider_name]['id'],
access_urls=[link['href'] for link in access_urls=access_urls))
responder[provider_name]['links']])
)
if 'status' in responder[provider_name]: if 'status' in responder[provider_name]:
provider_details_dict[provider_name].status = ( provider_details_dict[provider_name].status = (
responder[provider_name]['status']) responder[provider_name]['status'])
else: else:
provider_details_dict[provider_name].status = ( provider_details_dict[provider_name].status = 'deployed'
'deployed')
else:
provider_details_dict[provider_name] = (
provider_details.ProviderDetail(
error_info=responder[provider_name]['error_detail']
)
)
provider_details_dict[provider_name].status = 'failed'
service_controller.storage_controller.update_provider_details( service_controller.storage_controller.update_provider_details(
project_id, project_id,

View File

@ -31,6 +31,9 @@ def service_delete_worker(provider_details, service_controller,
responders.append(responder) responders.append(responder)
LOG.info('Deleting service from %s complete...' % provider) LOG.info('Deleting service from %s complete...' % provider)
# delete associated cname records from DNS
dns_responder = service_controller.dns_controller.delete(provider_details)
for responder in responders: for responder in responders:
# this is the item of responder, if there's "error" # this is the item of responder, if there's "error"
# key in it, it means the deletion for this provider failed. # key in it, it means the deletion for this provider failed.
@ -43,13 +46,19 @@ def service_delete_worker(provider_details, service_controller,
(provider_name, service_name)) (provider_name, service_name))
# stores the error info for debugging purposes. # stores the error info for debugging purposes.
provider_details[provider_name].error_info = ( provider_details[provider_name].error_info = (
responder[provider_name].get('error_info') responder[provider_name].get('error_info'))
) elif 'error' in dns_responder[provider_name]:
LOG.info('Delete service from DNS failed')
LOG.info('Updating provider detail status of %s for %s'.foramt(
(provider_name, service_name)))
# stores the error info for debugging purposes.
provider_details[provider_name].error_info = (
dns_responder[provider_name].get('error_info'))
else: else:
# delete service successful, remove this provider detail record # delete service successful, remove this provider detail record
del provider_details[provider_name] del provider_details[provider_name]
service_controller.storage_controller._driver.connect() service_controller.storage_controller._driver.connect()
if provider_details == {}: if provider_details == {}:
# Only if all provider successfully deleted we can delete # Only if all provider successfully deleted we can delete
# the poppy service. # the poppy service.
@ -65,4 +74,4 @@ def service_delete_worker(provider_details, service_controller,
service_controller.storage_controller.update_provider_details( service_controller.storage_controller.update_provider_details(
project_id, project_id,
service_name, service_name,
provider_details) provider_details)

View File

@ -32,17 +32,20 @@ def update_worker(service_controller, project_id, service_name,
responders.append(responder) responders.append(responder)
LOG.info(u'Updating service from {0} complete'.format(provider)) LOG.info(u'Updating service from {0} complete'.format(provider))
# create dns mapping
dns = service_controller.dns_controller
dns_responder = dns.update(service_old, service_updates, responders)
# gather links and status for service from providers # gather links and status for service from providers
provider_details_dict = {} provider_details_dict = {}
for responder in responders: for responder in responders:
for provider_name in responder: for provider_name in responder:
if 'error' not in responder[provider_name]: if 'error' not in responder[provider_name]:
access_urls = dns_responder[provider_name]['access_urls']
provider_details_dict[provider_name] = ( provider_details_dict[provider_name] = (
provider_details.ProviderDetail( provider_details.ProviderDetail(
provider_service_id=responder[provider_name]['id'], provider_service_id=responder[provider_name]['id'],
access_urls=[link['href'] for link in access_urls=access_urls))
responder[provider_name]['links']])
)
if 'status' in responder[provider_name]: if 'status' in responder[provider_name]:
provider_details_dict[provider_name].status = ( provider_details_dict[provider_name].status = (
responder[provider_name]['status']) responder[provider_name]['status'])

View File

@ -32,6 +32,7 @@ class DefaultServicesController(base.ServicesController):
self.storage_controller = self._driver.storage.services_controller self.storage_controller = self._driver.storage.services_controller
self.flavor_controller = self._driver.storage.flavors_controller self.flavor_controller = self._driver.storage.flavors_controller
self.dns_controller = self._driver.dns.services_controller
def _get_provider_details(self, project_id, service_name): def _get_provider_details(self, project_id, service_name):
try: try:
@ -86,6 +87,7 @@ class DefaultServicesController(base.ServicesController):
raise e raise e
self.storage_controller._driver.close_connection() self.storage_controller._driver.close_connection()
p = multiprocessing.Process( p = multiprocessing.Process(
name='Process: create poppy service %s for' name='Process: create poppy service %s for'
' project id: %s' % ' project id: %s' %
@ -141,6 +143,7 @@ class DefaultServicesController(base.ServicesController):
provider_details) provider_details)
self.storage_controller._driver.close_connection() self.storage_controller._driver.close_connection()
p = multiprocessing.Process( p = multiprocessing.Process(
name=('Process: update poppy service {0} for project id: {1}' name=('Process: update poppy service {0} for project id: {1}'
.format(service_name, project_id)), .format(service_name, project_id)),
@ -172,6 +175,7 @@ class DefaultServicesController(base.ServicesController):
provider_details) provider_details)
self.storage_controller._driver.close_connection() self.storage_controller._driver.close_connection()
p = multiprocessing.Process( p = multiprocessing.Process(
name='Process: delete poppy service %s for' name='Process: delete poppy service %s for'
' project id: %s' % ' project id: %s' %
@ -184,6 +188,7 @@ class DefaultServicesController(base.ServicesController):
project_id, project_id,
service_name)) service_name))
p.start() p.start()
return return
def purge(self, project_id, service_name, purge_url=None): def purge(self, project_id, service_name, purge_url=None):

View File

@ -26,7 +26,7 @@ class ProviderDetail(object):
"""ProviderDetail object for each provider.""" """ProviderDetail object for each provider."""
def __init__(self, provider_service_id=None, access_urls=[], def __init__(self, provider_service_id=None, access_urls={},
status=u"deploy_in_progress", name=None, error_info=None): status=u"deploy_in_progress", name=None, error_info=None):
self._provider_service_id = provider_service_id self._provider_service_id = provider_service_id
self._id = provider_service_id self._id = provider_service_id
@ -44,14 +44,14 @@ class ProviderDetail(object):
def provider_service_id(self, value): def provider_service_id(self, value):
self._provider_service_id = value self._provider_service_id = value
@property
def access_urls(self):
return self._access_urls
@property @property
def name(self): def name(self):
return self._name return self._name
@property
def access_urls(self):
return self._access_urls
@access_urls.setter @access_urls.setter
def access_urls(self, value): def access_urls(self, value):
self._access_urls = value self._access_urls = value

View File

@ -98,7 +98,8 @@ class ServiceController(base.ServiceBase):
LOG.info('Creating policy %s on domain %s complete' % LOG.info('Creating policy %s on domain %s complete' %
(dp, ','.join(classified_domain))) (dp, ','.join(classified_domain)))
links.append({'href': self.driver.akamai_access_url_link, links.append({'href': self.driver.akamai_access_url_link,
"rel": 'access_url' 'rel': 'access_url',
'domain': service_obj.name
}) })
except Exception: except Exception:
return self.responder.failed("failed to create service") return self.responder.failed("failed to create service")
@ -279,7 +280,8 @@ class ServiceController(base.ServiceBase):
LOG.info('Creating/Updateing policy %s on domain %s ' LOG.info('Creating/Updateing policy %s on domain %s '
'complete' % (dp, ','.join(classified_domain))) 'complete' % (dp, ','.join(classified_domain)))
links.append({'href': self.driver.akamai_access_url_link, links.append({'href': self.driver.akamai_access_url_link,
'rel': 'access_url' 'rel': 'access_url',
'domain': service_obj.name
}) })
except Exception: except Exception:
return self.responder.failed("failed to update service") return self.responder.failed("failed to update service")
@ -348,7 +350,9 @@ class ServiceController(base.ServiceBase):
return self.responder.failed("failed to update service") return self.responder.failed("failed to update service")
ids = policies ids = policies
links.append({'href': self.driver.akamai_access_url_link, links.append({'href': self.driver.akamai_access_url_link,
'rel': 'access_url'}) 'rel': 'access_url',
'domain': service_obj.name
})
return self.responder.updated(json.dumps(ids), links) return self.responder.updated(json.dumps(ids), links)
def delete(self, provider_service_id): def delete(self, provider_service_id):

View File

@ -50,7 +50,8 @@ class ServiceController(base.ServiceBase):
service_version.number) service_version.number)
links = [{"href": '.'.join([domain_check.domain.name, links = [{"href": '.'.join([domain_check.domain.name,
"global.prod.fastly.net"]), "global.prod.fastly.net"]),
"rel": 'access_url'} "rel": 'access_url',
"domain": domain_check.domain.name}
for domain_check in domain_checks] for domain_check in domain_checks]
for origin in service_obj.origins: for origin in service_obj.origins:

View File

@ -37,6 +37,7 @@ class ServiceController(base.ServiceBase):
service_id = uuid.uuid1() service_id = uuid.uuid1()
return self.responder.created(str(service_id), [{ return self.responder.created(str(service_id), [{
"href": "www.mysite.com", "href": "www.mysite.com",
"domain": "www.mydomain.com",
'rel': "access_url"}]) 'rel': "access_url"}])
def delete(self, provider_service_id): def delete(self, provider_service_id):

View File

@ -293,7 +293,7 @@ class ServicesController(base.ServicesController):
provider_detail_dict = json.loads( provider_detail_dict = json.loads(
provider_details_result[provider_name]) provider_details_result[provider_name])
provider_service_id = provider_detail_dict.get('id', None) provider_service_id = provider_detail_dict.get('id', None)
access_urls = provider_detail_dict.get("access_urls", None) access_urls = provider_detail_dict.get("access_urls", [])
status = provider_detail_dict.get("status", u'creating') status = provider_detail_dict.get("status", u'creating')
error_info = provider_detail_dict.get("error_info", None) error_info = provider_detail_dict.get("error_info", None)
provider_detail_obj = provider_details.ProviderDetail( provider_detail_obj = provider_details.ProviderDetail(

View File

@ -37,16 +37,17 @@ class ServicesController(base.ServicesController):
provider_details = { provider_details = {
'MaxCDN': json.dumps( 'MaxCDN': json.dumps(
{'id': 11942, {'id': 11942,
'access_urls': ['mypullzone.netdata.com']}), 'access_urls': [{'operator_url': 'mypullzone.netdata.com'}]}),
'Mock': json.dumps( 'Mock': json.dumps(
{'id': 73242, {'id': 73242,
'access_urls': ['mycdn.mock.com']}), 'access_urls': [{'operator_url': 'mycdn.mock.com'}]}),
'CloudFront': json.dumps( 'CloudFront': json.dumps(
{'id': '5ABC892', {'id': '5ABC892',
'access_urls': ['cf123.cloudcf.com']}), 'access_urls': [{'operator_url': 'cf123.cloudcf.com'}]}),
'Fastly': json.dumps( 'Fastly': json.dumps(
{'id': 3488, {'id': 3488,
'access_urls': ['mockcf123.fastly.prod.com']})} 'access_urls':
[{'operator_url': 'mockcf123.fastly.prod.com'}]})}
services = [{'name': 'mockdb1_service_name', services = [{'name': 'mockdb1_service_name',
'domains': [json.dumps({'domain': 'www.mywebsite.com'})], 'domains': [json.dumps({'domain': 'www.mywebsite.com'})],
@ -88,16 +89,17 @@ class ServicesController(base.ServicesController):
provider_details = { provider_details = {
'MaxCDN': json.dumps( 'MaxCDN': json.dumps(
{'id': 11942, {'id': 11942,
'access_urls': ['mypullzone.netdata.com']}), 'access_urls': [{'operator_url': 'mypullzone.netdata.com'}]}),
'Mock': json.dumps( 'Mock': json.dumps(
{'id': 73242, {'id': 73242,
'access_urls': ['mycdn.mock.com']}), 'access_urls': [{'operator_url': 'mycdn.mock.com'}]}),
'CloudFront': json.dumps( 'CloudFront': json.dumps(
{'id': '5ABC892', {'id': '5ABC892',
'access_urls': ['cf123.cloudcf.com']}), 'access_urls': [{'operator_url': 'cf123.cloudcf.com'}]}),
'Fastly': json.dumps( 'Fastly': json.dumps(
{'id': 3488, {'id': 3488,
'access_urls': ['mockcf123.fastly.prod.com']})} 'access_urls':
[{'operator_url': 'mockcf123.fastly.prod.com'}]})}
service_dict = {'name': service_name, service_dict = {'name': service_name,
'domains': [domain_json], 'domains': [domain_json],

View File

@ -49,10 +49,10 @@ class Model(collections.OrderedDict):
request.host_url, request.host_url,
self['name']))), self['name']))),
'self')] 'self')]
for provider_name in service_obj.provider_details: for provider_name in service_obj.provider_details:
for access_url in ( provider_detail = service_obj.provider_details[provider_name]
service_obj.provider_details[provider_name].access_urls): access_urls = provider_detail.access_urls
for access_url in access_urls:
self["links"].append(link.Model( self["links"].append(link.Model(
access_url, access_url['operator_url'],
'access_url')) 'access_url'))

View File

@ -0,0 +1 @@
pyrax

View File

@ -1,8 +1,9 @@
[drivers] [drivers]
providers = mock,cloudfront,fastly providers = mock,maxcdn,cloudfront,fastly
transport = pecan transport = pecan
manager = default manager = default
storage = mockdb storage = mockdb
dns = default
[drivers:storage:cassandra] [drivers:storage:cassandra]
cluster = "192.168.59.103" cluster = "192.168.59.103"