Neutron Jobs API for SG auto port update checks
- Adding the response model - Adding the client and behaviors for GET calls - Adding the composites and constants Change-Id: I8d6c962b5ed8ddbe0181f32283b8de657db9f4c1
This commit is contained in:
parent
de93ab7732
commit
7a13551cac
|
@ -0,0 +1,15 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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.
|
||||
"""
|
|
@ -0,0 +1,106 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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 cloudcafe.networking.networks.common.behaviors \
|
||||
import NetworkingBaseBehaviors
|
||||
from cloudcafe.networking.networks.extensions.jobs_api.constants \
|
||||
import JobsResource, JobsResponseCodes
|
||||
|
||||
|
||||
class JobsBehaviors(NetworkingBaseBehaviors):
|
||||
|
||||
def __init__(self, jobs_client):
|
||||
super(JobsBehaviors, self).__init__()
|
||||
self.client = jobs_client
|
||||
self.response_codes = JobsResponseCodes
|
||||
self.jobs_resource = JobsResource(JobsResource.JOB)
|
||||
|
||||
def get_job(self, job_id, resource_get_attempts=None,
|
||||
raise_exception=False, poll_interval=None):
|
||||
"""Get job by ID and verifies response
|
||||
|
||||
Args:
|
||||
job_id (str): job ID
|
||||
resource_get_attempts (Optional[int]): number of API retries
|
||||
raise_exception (Optional[bool]): flag to raise an exception
|
||||
if the GET call response is unexpected (default set to False).
|
||||
poll_interval (Optional[int]): sleep time interval between API
|
||||
retries
|
||||
|
||||
Returns:
|
||||
common.behaviors.NetworkingResponse object with API response and
|
||||
failure list with failures if any.
|
||||
"""
|
||||
|
||||
result = self._get_resource(
|
||||
resource=self.jobs_resource, resource_id=job_id,
|
||||
resource_get_attempts=resource_get_attempts,
|
||||
raise_exception=raise_exception, poll_interval=poll_interval)
|
||||
|
||||
return result
|
||||
|
||||
def list_jobs(self, job_id=None, tenant_id=None, transaction_id=None,
|
||||
parent_id=None, subtransactions=None,
|
||||
completed_subtransactions=None, transaction_percent=None,
|
||||
completed=None, action=None, created_at=None, limit=None,
|
||||
marker=None, page_reverse=None,
|
||||
resource_list_attempts=None, raise_exception=False,
|
||||
poll_interval=None):
|
||||
"""List jobs and verifies the response
|
||||
|
||||
Args:
|
||||
job_id (Optional[str]): get job with this ID.
|
||||
tenant_id (Optional[str]): get jobs for this tenant ID.
|
||||
transaction_id (Optional[str]): get jobs with this transaction ID.
|
||||
parent_id (Optional[str]): get jobs with this parent ID.
|
||||
subtransactions (Optional[int]): get jobs with this number of
|
||||
subtransactions.
|
||||
completed_subtransactions (Optional[int]): get jobs with this
|
||||
number of completed subtransactions.
|
||||
transaction_percent (Optional[int]): get jobs with this completion
|
||||
percentage.
|
||||
completed (Optional[bool]): get jobs with this true or false flag.
|
||||
action (Optional[str]): get jobs with this action,
|
||||
for ex. create sg rule <sg_rule_id> or update port <port_id>.
|
||||
created_at (Optional[str]): get jobs with this creation date.
|
||||
limit (Optional[int]): page size.
|
||||
marker (Optional[str]): ID of the last item of the previous page.
|
||||
page_reverse (Optional[bool]): direction of the page.
|
||||
resource_list_attempts (Optional[int]): number of API retries
|
||||
raise_exception (Optional[bool]): flag to raise an exception
|
||||
if the GET call response is unexpected (default set to False).
|
||||
poll_interval (Optional[int]): sleep time interval between API
|
||||
retries
|
||||
|
||||
Returns:
|
||||
common.behaviors.NetworkingResponse object with API response and
|
||||
failure list with failures if any.
|
||||
"""
|
||||
params_kwargs = dict(
|
||||
job_id=job_id, tenant_id=tenant_id, transaction_id=transaction_id,
|
||||
parent_id=parent_id, subtransactions=subtransactions,
|
||||
completed_subtransactions=completed_subtransactions,
|
||||
transaction_percent=transaction_percent, completed=completed,
|
||||
action=action, created_at=created_at, limit=limit, marker=marker,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
result = self._list_resources(
|
||||
resource=self.jobs_resource,
|
||||
resource_list_attempts=resource_list_attempts,
|
||||
raise_exception=raise_exception, poll_interval=poll_interval,
|
||||
params_kwargs=params_kwargs)
|
||||
|
||||
return result
|
|
@ -0,0 +1,112 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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 cafe.engine.http.client import AutoMarshallingHTTPClient
|
||||
from cloudcafe.networking.networks.extensions.jobs_api.models.response \
|
||||
import Job, Jobs
|
||||
|
||||
|
||||
class JobsClient(AutoMarshallingHTTPClient):
|
||||
"""Networking jobs client for GET calls.
|
||||
|
||||
Attributes:
|
||||
url (str): Base URL for the networks service.
|
||||
auth_token (str): Auth token to be used for all requests.
|
||||
serialize_format (str): Format for serializing requests.
|
||||
deserialize_format (str): Format for de-serializing responses.
|
||||
tenant_id (Optional[str]): tenant id to be included in the header
|
||||
if given.
|
||||
"""
|
||||
|
||||
def __init__(self, url, auth_token, serialize_format=None,
|
||||
deserialize_format=None, tenant_id=None):
|
||||
|
||||
super(JobsClient, self).__init__(serialize_format, deserialize_format)
|
||||
|
||||
self.auth_token = auth_token
|
||||
self.default_headers['X-Auth-Token'] = auth_token
|
||||
ct = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application', content_subtype=self.serialize_format)
|
||||
accept = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application',
|
||||
content_subtype=self.deserialize_format)
|
||||
self.default_headers['Content-Type'] = ct
|
||||
self.default_headers['Accept'] = accept
|
||||
if tenant_id:
|
||||
self.default_headers['X-Auth-Project-Id'] = tenant_id
|
||||
self.jobs_url = '{url}/jobs'.format(url=url)
|
||||
|
||||
def get_job(self, job_id, requestslib_kwargs=None):
|
||||
"""Get job by ID
|
||||
|
||||
Args:
|
||||
job_id (str): job ID
|
||||
|
||||
Returns:
|
||||
Requests.resonse object from the GET job with ID API call.
|
||||
"""
|
||||
|
||||
url = '{base_url}/{job_id}'.format(base_url=self.jobs_url,
|
||||
job_id=job_id)
|
||||
resp = self.request('GET', url, response_entity_type=Job,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def list_jobs(self, job_id=None, tenant_id=None, transaction_id=None,
|
||||
parent_id=None, subtransactions=None,
|
||||
completed_subtransactions=None, transaction_percent=None,
|
||||
completed=None, action=None, created_at=None, limit=None,
|
||||
marker=None, page_reverse=None, requestslib_kwargs=None):
|
||||
"""List jobs
|
||||
|
||||
Args:
|
||||
job_id (Optional[str]): get job with this ID.
|
||||
tenant_id (Optional[str]): get jobs for this tenant ID.
|
||||
transaction_id (Optional[str]): get jobs with this transaction ID.
|
||||
parent_id (Optional[str]): get jobs with this parent ID.
|
||||
subtransactions (Optional[int]): get jobs with this number of
|
||||
subtransactions.
|
||||
completed_subtransactions (Optional[int]): get jobs with this
|
||||
number of completed subtransactions.
|
||||
transaction_percent (Optional[int]): get jobs with this completion
|
||||
percentage.
|
||||
completed (Optional[bool]): get jobs with this true or false flag.
|
||||
action (Optional[str]): get jobs with this action,
|
||||
for ex. create sg rule <sg_rule_id> or update port <port_id>.
|
||||
created_at (Optional[str]): get jobs with this creation date.
|
||||
limit (Optional[int]): page size.
|
||||
marker (Optional[str]): ID of the last item of the previous page.
|
||||
page_reverse (Optional[bool]): direction of the page.
|
||||
|
||||
Returns:
|
||||
List of Requests.resonse objects from the GET jobs API call.
|
||||
The list may be filtered if optional args are given.
|
||||
"""
|
||||
|
||||
params = {'id': job_id, 'tenant_id': tenant_id,
|
||||
'transaction_id': transaction_id, 'parent_id': parent_id,
|
||||
'subtransactions': subtransactions,
|
||||
'completed_subtransactions': completed_subtransactions,
|
||||
'transaction_percent': transaction_percent,
|
||||
'completed': completed, 'action': action,
|
||||
'created_at': created_at, 'limit': limit, 'marker': marker,
|
||||
'page_reverse': page_reverse}
|
||||
|
||||
url = self.jobs_url
|
||||
resp = self.request('GET', url, params=params,
|
||||
response_entity_type=Jobs,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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 cloudcafe.networking.networks.composites import _NetworkingAuthComposite
|
||||
from cloudcafe.networking.networks.extensions.jobs_api.behaviors \
|
||||
import JobsBehaviors
|
||||
from cloudcafe.networking.networks.extensions.jobs_api.client \
|
||||
import JobsClient
|
||||
|
||||
|
||||
class JobsComposite(object):
|
||||
networking_auth_composite = _NetworkingAuthComposite
|
||||
|
||||
def __init__(self, auth_composite=None):
|
||||
auth_composite = auth_composite or self.networking_auth_composite()
|
||||
self.url = auth_composite.networking_url
|
||||
self.user = auth_composite._auth_user_config
|
||||
self.client = JobsClient(**auth_composite.client_args)
|
||||
|
||||
self.behaviors = JobsBehaviors(jobs_client=self.client)
|
|
@ -0,0 +1,41 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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 cloudcafe.networking.networks.common.constants \
|
||||
import NeutronResource, NeutronResponseCodes, NeutronErrorTypes
|
||||
|
||||
|
||||
class JobsResource(NeutronResource):
|
||||
"""Jobs resource types"""
|
||||
|
||||
# Resources to be used by the behavior
|
||||
JOB = 'job'
|
||||
JOBS = 'jobs'
|
||||
|
||||
PLURALS = NeutronResource.PLURALS
|
||||
PLURALS.update({JOB: JOBS})
|
||||
|
||||
|
||||
class JobsResponseCodes(NeutronResponseCodes):
|
||||
"""HTTP Jobs API Response codes"""
|
||||
|
||||
GET_JOB = 200
|
||||
LIST_JOBS = 200
|
||||
|
||||
|
||||
class JobsErrorTypes(NeutronErrorTypes):
|
||||
"""Jobs Error Types"""
|
||||
|
||||
JOB_NOT_FOUND = 'JobNotFound'
|
|
@ -0,0 +1,15 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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.
|
||||
"""
|
|
@ -0,0 +1,107 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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 copy
|
||||
import json
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingListModel, \
|
||||
AutoMarshallingModel
|
||||
|
||||
|
||||
class Job(AutoMarshallingModel):
|
||||
"""Networking Job model object to track the auto port update transactions
|
||||
done by adding and deleting security group rules
|
||||
|
||||
Attributes:
|
||||
id (str): job ID.
|
||||
tenant_id (str): user tenant ID.
|
||||
transaction_id (str): multiple jobs can belong to one transaction.
|
||||
subtransactions and parents will have the same transaction_id.
|
||||
parent_id (str): parent ID (may not always be used and set to None).
|
||||
subtransactions (int): number of child jobs.
|
||||
completed_subtransactions (int): number of subtransactions completed.
|
||||
transaction_percent (int): job completion percentage (100 for done).
|
||||
completed (bool): set to true when the job is done.
|
||||
action (str): job description, for ex. create sg rule <sg_rule_id>
|
||||
or update port <port_id>.
|
||||
created_at (str): creation date, for ex. 2016-10-07 16:16:00.
|
||||
"""
|
||||
JOB = 'job'
|
||||
|
||||
def __init__(self, id_=None, tenant_id=None, transaction_id=None,
|
||||
parent_id=None, subtransactions=None,
|
||||
completed_subtransactions=None, transaction_percent=None,
|
||||
completed=None, action=None, created_at=None, **kwargs):
|
||||
|
||||
# kwargs is to be used for extensions or checking unexpected attrs
|
||||
super(Job, self).__init__()
|
||||
self.id = id_
|
||||
self.tenant_id = tenant_id
|
||||
self.transaction_id = transaction_id
|
||||
self.parent_id = parent_id
|
||||
self.subtransactions = subtransactions
|
||||
self.completed_subtransactions = completed_subtransactions
|
||||
self.transaction_percent = transaction_percent
|
||||
self.completed = completed
|
||||
self.action = action
|
||||
self.created_at = created_at
|
||||
self.kwargs = kwargs
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return job object from a JSON serialized string"""
|
||||
|
||||
ret = None
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.JOB in json_dict:
|
||||
job_dict = json_dict.get(cls.JOB)
|
||||
ret = Job(**job_dict)
|
||||
return ret
|
||||
|
||||
|
||||
class Jobs(AutoMarshallingListModel):
|
||||
|
||||
JOBS = 'jobs'
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return a list of job objects from a JSON serialized string"""
|
||||
|
||||
ret = cls()
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.JOBS in json_dict:
|
||||
jobs = json_dict.get(cls.JOBS)
|
||||
for job in jobs:
|
||||
ret.append(Job(**job))
|
||||
return ret
|
Loading…
Reference in New Issue