Adds support for operator status
This patch adds support of operator_status. This can be used for enabling or disabling a service. Implements: blueprint enable-disable-service Change-Id: I458abb7b34b88a823118af5f5da6f82555d34a2d
This commit is contained in:
@@ -106,6 +106,8 @@ shared_ssl_num_shards = 5
|
||||
shared_ssl_shard_prefix = "scdn"
|
||||
shared_ssl_domain_suffix = "secure.poppycdn.net"
|
||||
url = "poppycdn.net"
|
||||
# link to page to be directed to when a service is disabled
|
||||
url_404 = notfound.com
|
||||
# You email associated with DNS, for notifications
|
||||
email = "your@email.com"
|
||||
auth_endpoint = ""
|
||||
@@ -149,4 +151,3 @@ san_cert_hostname_limit = "MY_SAN_HOSTNAMES_LMIT"
|
||||
identity_url = OPENSTACK_IDENTITY_URL
|
||||
preferred_dcs = DC1,DC2
|
||||
container_name = .CDN_ACCESS_LOGS
|
||||
|
||||
|
||||
@@ -41,3 +41,13 @@ class ServiceStatusNeitherDeployedNorFailed(Exception):
|
||||
class ServiceStatusNotDeployed(Exception):
|
||||
|
||||
"""Raised when a non-deployed service is purged."""
|
||||
|
||||
|
||||
class ServiceStatusDisabled(Exception):
|
||||
|
||||
"""Raised when a disabled status is updated."""
|
||||
|
||||
|
||||
class InvalidServiceState(Exception):
|
||||
|
||||
"""Raised when a operator state is updated with an invalid status."""
|
||||
|
||||
41
poppy/distributed_task/taskflow/flow/update_service_state.py
Normal file
41
poppy/distributed_task/taskflow/flow/update_service_state.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# 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.
|
||||
|
||||
from oslo.config import cfg
|
||||
from taskflow.patterns import linear_flow
|
||||
|
||||
from poppy.distributed_task.taskflow.task import update_service_state_tasks
|
||||
from poppy.openstack.common import log
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
conf = cfg.CONF
|
||||
conf(project='poppy', prog='poppy', args=[])
|
||||
|
||||
|
||||
def disable_service():
|
||||
flow = linear_flow.Flow('Breaking CNAME chain').add(
|
||||
update_service_state_tasks.BreakDNSChainTask()
|
||||
)
|
||||
return flow
|
||||
|
||||
|
||||
def enable_service():
|
||||
flow = linear_flow.Flow('Fixing CNAME chain').add(
|
||||
update_service_state_tasks.FixDNSChainTask()
|
||||
)
|
||||
return flow
|
||||
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) 2015 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 json
|
||||
|
||||
from oslo.config import cfg
|
||||
from taskflow import task
|
||||
|
||||
from poppy.distributed_task.utils import memoized_controllers
|
||||
from poppy.openstack.common import log
|
||||
from poppy.transport.pecan.models.request import service
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
conf = cfg.CONF
|
||||
conf(project='poppy', prog='poppy', args=[])
|
||||
|
||||
|
||||
class FixDNSChainTask(task.Task):
|
||||
def execute(self, service_obj):
|
||||
service_obj_json = json.loads(service_obj)
|
||||
service_obj = service.load_from_json(service_obj_json)
|
||||
|
||||
service_controller, dns = \
|
||||
memoized_controllers.task_controllers('poppy', 'dns')
|
||||
|
||||
LOG.info(u'Starting to enable service')
|
||||
dns.enable(service_obj)
|
||||
LOG.info(u'Enabled service')
|
||||
|
||||
return
|
||||
|
||||
|
||||
class BreakDNSChainTask(task.Task):
|
||||
def execute(self, service_obj):
|
||||
service_obj_json = json.loads(service_obj)
|
||||
service_obj = service.load_from_json(service_obj_json)
|
||||
|
||||
service_controller, dns = \
|
||||
memoized_controllers.task_controllers('poppy', 'dns')
|
||||
|
||||
LOG.info(u'Starting to disable service')
|
||||
dns.disable(service_obj)
|
||||
LOG.info(u'Disabled service')
|
||||
|
||||
return
|
||||
@@ -49,6 +49,8 @@ RACKSPACE_OPTIONS = [
|
||||
help='Authentication end point for DNS'),
|
||||
cfg.IntOpt('timeout', default=30, help='DNS response timeout'),
|
||||
cfg.IntOpt('delay', default=1, help='DNS retry delay'),
|
||||
cfg.StrOpt('url_404', default='',
|
||||
help='The url to CNAME to when a service is disabled'),
|
||||
]
|
||||
|
||||
RACKSPACE_GROUP = 'drivers:dns:rackspace'
|
||||
|
||||
@@ -103,11 +103,12 @@ class ServicesController(base.ServicesBase):
|
||||
subdomain.add_records(cname_records)
|
||||
return dns_links
|
||||
|
||||
def _delete_cname_record(self, access_url, shared_ssl_flag):
|
||||
"""Delete a CNAME record
|
||||
def _search_cname_record(self, access_url, shared_ssl_flag):
|
||||
"""Search a CNAME record
|
||||
|
||||
:param access_url: DNS Access URL
|
||||
:return error_msg: returns error message, if any
|
||||
:param shared_ssl_flag: flag indicating if this is a shared ssl domain
|
||||
:return records: returns records, if any
|
||||
"""
|
||||
|
||||
# extract shard name
|
||||
@@ -129,17 +130,51 @@ class ServicesController(base.ServicesBase):
|
||||
name = access_url
|
||||
record_type = 'CNAME'
|
||||
records = self.client.search_records(subdomain, record_type, name)
|
||||
|
||||
return records
|
||||
|
||||
def _delete_cname_record(self, access_url, shared_ssl_flag):
|
||||
"""Delete a CNAME record
|
||||
|
||||
:param access_url: DNS Access URL
|
||||
:param shared_ssl_flag: flag indicating if this is a shared ssl domain
|
||||
:return error_msg: returns error message, if any
|
||||
"""
|
||||
|
||||
records = self._search_cname_record(access_url, shared_ssl_flag)
|
||||
# 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
|
||||
elif len(records) == 1:
|
||||
LOG.info('Deleting DNS records for : {0}'.format(access_url))
|
||||
records[0].delete()
|
||||
return
|
||||
|
||||
def _change_cname_record(self, access_url, target_url, shared_ssl_flag):
|
||||
"""Change a CNAME record
|
||||
|
||||
:param access_url: DNS Access URL
|
||||
:param target_url: Operator Access URL
|
||||
:param shared_ssl_flag: flag indicating if this is a shared ssl domain
|
||||
:return error_msg: returns error message, if any
|
||||
"""
|
||||
|
||||
records = self._search_cname_record(access_url, shared_ssl_flag)
|
||||
# we should get one record, or none if it has been deleted already
|
||||
if not records:
|
||||
LOG.info('DNS record not found for: {0}'.format(access_url))
|
||||
elif len(records) > 1:
|
||||
LOG.info('Multiple DNS records found: {0}'.format(access_url))
|
||||
elif len(records) == 1:
|
||||
LOG.info('Updating DNS record for : {0}'.format(access_url))
|
||||
records[0].update(data=target_url)
|
||||
LOG.info('Updated DNS record for : {0}'.format(access_url))
|
||||
|
||||
return
|
||||
|
||||
def _generate_sharded_domain_name(self, shard_prefix, num_shards, suffix):
|
||||
@@ -498,3 +533,55 @@ class ServicesController(base.ServicesBase):
|
||||
dns_details[provider_name] = {'access_urls': access_urls}
|
||||
|
||||
return self.responder.updated(dns_details)
|
||||
|
||||
def gather_cname_links(self, service_obj):
|
||||
provider_details = service_obj.provider_details
|
||||
dns_details = {}
|
||||
for provider_name in provider_details:
|
||||
access_urls = []
|
||||
for link in provider_details[provider_name].access_urls:
|
||||
# if this is a log delivery URL, don't add
|
||||
if 'log_delivery' in link:
|
||||
continue
|
||||
|
||||
access_url = {
|
||||
'domain': link['domain'],
|
||||
'provider_url': link['provider_url'],
|
||||
'operator_url': link['operator_url']
|
||||
}
|
||||
# Need to indicate if this access_url is a shared ssl
|
||||
# access url, since its has different shard_prefix and
|
||||
# num_shard
|
||||
if link.get('certificate', None) == 'shared':
|
||||
access_url['shared_ssl_flag'] = True
|
||||
else:
|
||||
access_url['shared_ssl_flag'] = False
|
||||
|
||||
access_urls.append(access_url)
|
||||
dns_details[provider_name] = {'access_urls': access_urls}
|
||||
|
||||
return dns_details
|
||||
|
||||
def enable(self, service_obj):
|
||||
dns_details = self.gather_cname_links(service_obj)
|
||||
for provider_name in dns_details:
|
||||
access_urls = dns_details[provider_name]['access_urls']
|
||||
for access_url in access_urls:
|
||||
provider_url = access_url['provider_url']
|
||||
operator_url = access_url['operator_url']
|
||||
shared_ssl_flag = access_url['shared_ssl_flag']
|
||||
self._change_cname_record(operator_url,
|
||||
provider_url,
|
||||
shared_ssl_flag)
|
||||
|
||||
def disable(self, service_obj):
|
||||
dns_details = self.gather_cname_links(service_obj)
|
||||
provider_url = self._driver.rackdns_conf.url_404
|
||||
for provider_name in dns_details:
|
||||
access_urls = dns_details[provider_name]['access_urls']
|
||||
for access_url in access_urls:
|
||||
operator_url = access_url['operator_url']
|
||||
shared_ssl_flag = access_url['shared_ssl_flag']
|
||||
self._change_cname_record(operator_url,
|
||||
provider_url,
|
||||
shared_ssl_flag)
|
||||
|
||||
@@ -72,6 +72,16 @@ class ServicesControllerBase(controller.ManagerControllerBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_state(self, project_id, service_id, state):
|
||||
"""update_state
|
||||
|
||||
:param project_id
|
||||
:param service_id
|
||||
:param state
|
||||
:raises ValueError
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete(self, project_id, service_id):
|
||||
"""DELETE
|
||||
|
||||
@@ -24,6 +24,7 @@ from poppy.distributed_task.taskflow.flow import create_service
|
||||
from poppy.distributed_task.taskflow.flow import delete_service
|
||||
from poppy.distributed_task.taskflow.flow import purge_service
|
||||
from poppy.distributed_task.taskflow.flow import update_service
|
||||
from poppy.distributed_task.taskflow.flow import update_service_state
|
||||
from poppy.manager import base
|
||||
from poppy.model.helpers import rule
|
||||
from poppy.model import service
|
||||
@@ -142,6 +143,7 @@ class DefaultServicesController(base.ServicesController):
|
||||
:param service_obj
|
||||
:raises LookupError, ValueError
|
||||
"""
|
||||
|
||||
try:
|
||||
flavor = self.flavor_controller.get(service_json.get('flavor_id'))
|
||||
# raise a lookup error if the flavor is not found
|
||||
@@ -203,6 +205,10 @@ class DefaultServicesController(base.ServicesController):
|
||||
except ValueError:
|
||||
raise errors.ServiceNotFound("Service not found")
|
||||
|
||||
if service_old.operator_status == u'disabled':
|
||||
raise errors.ServiceStatusDisabled(
|
||||
u'Service {0} is disabled'.format(service_id))
|
||||
|
||||
if service_old.status not in [u'deployed', u'failed']:
|
||||
raise errors.ServiceStatusNeitherDeployedNorFailed(
|
||||
u'Service {0} neither deployed nor failed'.format(service_id))
|
||||
@@ -221,6 +227,7 @@ class DefaultServicesController(base.ServicesController):
|
||||
# remove fields that cannot be part of PATCH
|
||||
del service_old_json['service_id']
|
||||
del service_old_json['status']
|
||||
del service_old_json['operator_status']
|
||||
del service_old_json['provider_details']
|
||||
|
||||
service_new_json = jsonpatch.apply_patch(
|
||||
@@ -283,6 +290,34 @@ class DefaultServicesController(base.ServicesController):
|
||||
|
||||
return
|
||||
|
||||
def update_state(self, project_id, service_id, state):
|
||||
"""update_state.
|
||||
|
||||
:param project_id
|
||||
:param service_id
|
||||
:param state
|
||||
|
||||
:raises ValueError
|
||||
"""
|
||||
# call storage and update service state
|
||||
try:
|
||||
service_obj = self.storage_controller.update_state(project_id,
|
||||
service_id,
|
||||
state)
|
||||
except ValueError:
|
||||
raise errors.ServiceNotFound("Service not found")
|
||||
|
||||
kwargs = {
|
||||
'service_obj': json.dumps(service_obj.to_dict())
|
||||
}
|
||||
|
||||
if state == 'enabled':
|
||||
self.distributed_task_controller.submit_task(
|
||||
update_service_state.enable_service, **kwargs)
|
||||
elif state == 'disabled':
|
||||
self.distributed_task_controller.submit_task(
|
||||
update_service_state.disable_service, **kwargs)
|
||||
|
||||
def delete(self, project_id, service_id):
|
||||
"""delete.
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ class Service(common.DictSerializableModel):
|
||||
flavor_id,
|
||||
caching=[],
|
||||
restrictions=[],
|
||||
log_delivery=None):
|
||||
log_delivery=None,
|
||||
operator_status='enabled'):
|
||||
self._service_id = str(service_id)
|
||||
self._name = name
|
||||
self._domains = domains
|
||||
@@ -50,6 +51,7 @@ class Service(common.DictSerializableModel):
|
||||
self._log_delivery = log_delivery or ld.LogDelivery(False)
|
||||
self._status = 'create_in_progress'
|
||||
self._provider_details = {}
|
||||
self._operator_status = operator_status
|
||||
|
||||
@property
|
||||
def service_id(self):
|
||||
@@ -124,6 +126,16 @@ class Service(common.DictSerializableModel):
|
||||
"""Set log_delivery."""
|
||||
self._log_delivery = value
|
||||
|
||||
@property
|
||||
def operator_status(self):
|
||||
"""Get operator status."""
|
||||
return self._operator_status
|
||||
|
||||
@operator_status.setter
|
||||
def operator_status(self, value):
|
||||
"""Set operator status."""
|
||||
self._operator_status = value
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
"""Get or set status.
|
||||
|
||||
@@ -56,6 +56,21 @@ class ServicesControllerBase(controller.StorageControllerBase):
|
||||
:param project_id
|
||||
:param service_id
|
||||
:param service_json
|
||||
|
||||
:returns service_obj
|
||||
:raise NotImplementedError
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_state(self, project_id, service_id, state):
|
||||
"""update_state
|
||||
|
||||
Update service state
|
||||
|
||||
:param project_id
|
||||
:param service_id
|
||||
:param state
|
||||
:raise NotImplementedError
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE services ADD operator_status varchar;
|
||||
ALTER TABLE archives ADD operator_status varchar;
|
||||
|
||||
--//@UNDO
|
||||
|
||||
ALTER TABLE services DROP operator_status;
|
||||
ALTER TABLE archives DROP operator_status;
|
||||
@@ -60,6 +60,7 @@ CQL_LIST_SERVICES = '''
|
||||
caching_rules,
|
||||
restrictions,
|
||||
provider_details,
|
||||
operator_status,
|
||||
log_delivery
|
||||
FROM services
|
||||
WHERE project_id = %(project_id)s
|
||||
@@ -78,6 +79,7 @@ CQL_GET_SERVICE = '''
|
||||
caching_rules,
|
||||
restrictions,
|
||||
provider_details,
|
||||
operator_status,
|
||||
log_delivery
|
||||
FROM services
|
||||
WHERE project_id = %(project_id)s AND service_id = %(service_id)s
|
||||
@@ -116,6 +118,7 @@ CQL_ARCHIVE_SERVICE = '''
|
||||
caching_rules,
|
||||
restrictions,
|
||||
provider_details,
|
||||
operator_status,
|
||||
archived_time
|
||||
)
|
||||
VALUES (%(project_id)s,
|
||||
@@ -127,6 +130,7 @@ CQL_ARCHIVE_SERVICE = '''
|
||||
%(caching_rules)s,
|
||||
%(restrictions)s,
|
||||
%(provider_details)s,
|
||||
%(operator_status)s,
|
||||
%(archived_time)s)
|
||||
|
||||
DELETE FROM services
|
||||
@@ -157,6 +161,7 @@ CQL_CREATE_SERVICE = '''
|
||||
caching_rules,
|
||||
restrictions,
|
||||
provider_details,
|
||||
operator_status,
|
||||
log_delivery
|
||||
)
|
||||
VALUES (%(project_id)s,
|
||||
@@ -168,6 +173,7 @@ CQL_CREATE_SERVICE = '''
|
||||
%(caching_rules)s,
|
||||
%(restrictions)s,
|
||||
%(provider_details)s,
|
||||
%(operator_status)s,
|
||||
%(log_delivery)s)
|
||||
'''
|
||||
|
||||
@@ -329,7 +335,8 @@ class ServicesController(base.ServicesController):
|
||||
'caching_rules': caching_rules,
|
||||
'restrictions': restrictions,
|
||||
'log_delivery': log_delivery,
|
||||
'provider_details': {}
|
||||
'provider_details': {},
|
||||
'operator_status': 'enabled'
|
||||
}
|
||||
|
||||
LOG.debug("Creating New Service - {0} ({1})".format(service_id,
|
||||
@@ -390,7 +397,8 @@ class ServicesController(base.ServicesController):
|
||||
'caching_rules': caching_rules,
|
||||
'restrictions': restrictions,
|
||||
'provider_details': pds,
|
||||
'log_delivery': log_delivery
|
||||
'log_delivery': log_delivery,
|
||||
'operator_status': service_obj.operator_status
|
||||
}
|
||||
|
||||
stmt = query.SimpleStatement(
|
||||
@@ -422,6 +430,24 @@ class ServicesController(base.ServicesController):
|
||||
domain_args)
|
||||
self.session.execute(batch_claim)
|
||||
|
||||
def update_state(self, project_id, service_id, state):
|
||||
"""update_state
|
||||
|
||||
Update service state
|
||||
|
||||
:param project_id
|
||||
:param service_id
|
||||
:param state
|
||||
|
||||
:returns service_obj
|
||||
"""
|
||||
|
||||
service_obj = self.get(project_id, service_id)
|
||||
service_obj.operator_status = state
|
||||
self.update(project_id, service_id, service_obj)
|
||||
|
||||
return service_obj
|
||||
|
||||
def delete(self, project_id, service_id):
|
||||
"""delete.
|
||||
|
||||
@@ -455,6 +481,8 @@ class ServicesController(base.ServicesController):
|
||||
'caching_rules': result.get('caching_rules', []),
|
||||
'restrictions': result.get('restrictions', []),
|
||||
'provider_details': pds,
|
||||
'operator_status': result.get('operator_status',
|
||||
'enabled'),
|
||||
'archived_time': datetime.datetime.utcnow(),
|
||||
'domains_list': query.ValueSequence(domains_list)
|
||||
}
|
||||
@@ -574,6 +602,7 @@ class ServicesController(base.ServicesController):
|
||||
caching_rules = [json.loads(c) for c in result.get('caching_rules', [])
|
||||
or []]
|
||||
log_delivery = json.loads(result.get('log_delivery', '{}') or '{}')
|
||||
operator_status = result.get('operator_status', 'enabled')
|
||||
|
||||
# create models for each item
|
||||
origins = [
|
||||
@@ -613,7 +642,8 @@ class ServicesController(base.ServicesController):
|
||||
s = service.Service(service_id, name, domains, origins, flavor_id,
|
||||
caching=caching_rules,
|
||||
restrictions=restrictions,
|
||||
log_delivery=log_delivery)
|
||||
log_delivery=log_delivery,
|
||||
operator_status=operator_status)
|
||||
|
||||
# format the provider details
|
||||
provider_detail_results = result.get('provider_details') or {}
|
||||
|
||||
@@ -151,6 +151,24 @@ class ServicesController(base.ServicesController):
|
||||
# update configuration in storage
|
||||
return ''
|
||||
|
||||
def update_state(self, project_id, service_id, state):
|
||||
"""update_state
|
||||
|
||||
Update service state
|
||||
|
||||
:param project_id
|
||||
:param service_id
|
||||
:param state
|
||||
|
||||
:returns service_obj
|
||||
"""
|
||||
|
||||
service_obj = self.get(project_id, service_id)
|
||||
service_obj.operator_status = state
|
||||
self.update(project_id, service_id, service_obj)
|
||||
|
||||
return self.get(project_id, service_id)
|
||||
|
||||
def delete(self, project_id, service_id):
|
||||
if (service_id in self.created_service_ids):
|
||||
self.created_service_ids.remove(service_id)
|
||||
|
||||
@@ -75,6 +75,38 @@ class ServiceAssetsController(base.Controller, hooks.HookController):
|
||||
return pecan.Response(None, 202)
|
||||
|
||||
|
||||
class OperatorStateController(base.Controller, hooks.HookController):
|
||||
|
||||
__hooks__ = [poppy_hooks.Context(), poppy_hooks.Error()]
|
||||
|
||||
def __init__(self, driver):
|
||||
super(OperatorStateController, self).__init__(driver)
|
||||
|
||||
@pecan.expose('json')
|
||||
def post(self, service_id):
|
||||
|
||||
service_state_json = json.loads(pecan.request.body.decode('utf-8'))
|
||||
service_state = service_state_json.get('state', None)
|
||||
services_controller = self._driver.manager.services_controller
|
||||
|
||||
if not service_state:
|
||||
pecan.abort(400, detail='Invalid JSON, state is a required field')
|
||||
|
||||
if service_state not in [u'enabled', u'disabled']:
|
||||
pecan.abort(400, detail=u'Service state {0} is invalid'
|
||||
.format(service_state))
|
||||
|
||||
try:
|
||||
services_controller.update_state(self.project_id,
|
||||
service_id,
|
||||
service_state)
|
||||
except ValueError:
|
||||
pecan.abort(404, detail='Service {0} could not be found'.format(
|
||||
service_id))
|
||||
|
||||
return pecan.Response(None, 202)
|
||||
|
||||
|
||||
class ServicesController(base.Controller, hooks.HookController):
|
||||
|
||||
__hooks__ = [poppy_hooks.Context(), poppy_hooks.Error()]
|
||||
@@ -91,6 +123,7 @@ class ServicesController(base.Controller, hooks.HookController):
|
||||
# so added it in __init__ method.
|
||||
# see more in: http://pecan.readthedocs.org/en/latest/rest.html
|
||||
self.__class__.assets = ServiceAssetsController(driver)
|
||||
self.__class__.state = OperatorStateController(driver)
|
||||
|
||||
@pecan.expose('json')
|
||||
def get_all(self):
|
||||
|
||||
@@ -42,9 +42,11 @@ class Model(collections.OrderedDict):
|
||||
service_obj.restrictions]
|
||||
self["caching"] = [cachingrules.Model(c) for c in
|
||||
service_obj.caching]
|
||||
self["status"] = service_obj.status
|
||||
self["flavor_id"] = service_obj.flavor_id
|
||||
self["log_delivery"] = log_delivery.Model(service_obj.log_delivery)
|
||||
self["status"] = service_obj.status
|
||||
if service_obj.operator_status == "disabled":
|
||||
self["status"] = service_obj.operator_status
|
||||
|
||||
self["errors"] = []
|
||||
|
||||
|
||||
@@ -338,7 +338,8 @@ class ServiceSchema(schema_base.SchemaBase):
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
}
|
||||
},
|
||||
'PATCH': {
|
||||
'type': 'array',
|
||||
'properties': {
|
||||
|
||||
@@ -474,10 +474,6 @@ class ServiceControllerTest1(base.FunctionalTest):
|
||||
self.assertEqual(202, response.status_code)
|
||||
self.assertTrue('Location' in response.headers)
|
||||
self.service_url = urlparse.urlparse(response.headers["Location"]).path
|
||||
# import pdb; pdb.set_trace()
|
||||
# print '#############################################################'
|
||||
# print self.service_url
|
||||
# print '#############################################################'
|
||||
|
||||
def tearDown(self):
|
||||
super(ServiceControllerTest1, self).tearDown()
|
||||
@@ -492,15 +488,10 @@ class ServiceControllerTest1(base.FunctionalTest):
|
||||
|
||||
def test_update_with_good_input(self):
|
||||
self.skipTest('Skip failing test')
|
||||
# import pdb; pdb.set_trace()
|
||||
# print '###################################'
|
||||
# print self.service_url
|
||||
response = self.app.get(
|
||||
self.service_url,
|
||||
headers={'X-Project-ID': self.project_id})
|
||||
self.assertEqual(200, response.status_code)
|
||||
# print '###################################'
|
||||
# print self.service_url
|
||||
# update with good data
|
||||
response = self.app.patch(self.service_url,
|
||||
params=json.dumps([
|
||||
|
||||
Reference in New Issue
Block a user