add patch upgrade history
Change-Id: I542786f31c9118c802def968381ac43850d10e52
This commit is contained in:
parent
1016c7da42
commit
0ec893e8cb
@ -1282,3 +1282,10 @@ def upgrade_os(req, version_id, version_patch_id, update_file,
|
||||
host_meta['version_patch_id'] = version_patch_id
|
||||
daisy_cmn.update_db_host_status(req, host['id'], host_meta,
|
||||
version_id)
|
||||
if version_patch_id:
|
||||
patch_meta = {'host_id': host['id'],
|
||||
'patch_name': update_file,
|
||||
'version_id': version_id,
|
||||
'type': update_object}
|
||||
registry.add_host_patch_history_metadata(
|
||||
req.context, patch_meta)
|
||||
|
@ -596,6 +596,14 @@ class API(wsgi.Router):
|
||||
controller=version_patchs_resource,
|
||||
action='update_version_patch',
|
||||
conditions={'method': ['PUT']})
|
||||
mapper.connect("/patch_history",
|
||||
controller=version_patchs_resource,
|
||||
action='add_host_patch_history',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect("/patch_history/list",
|
||||
controller=version_patchs_resource,
|
||||
action='list_host_patch_history',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
template_configs_resource = template_configs.create_resource()
|
||||
mapper.connect("/template_configs/import_template_config",
|
||||
|
55
code/daisy/daisy/api/v1/version_patchs.py
Normal file → Executable file
55
code/daisy/daisy/api/v1/version_patchs.py
Normal file → Executable file
@ -190,6 +190,44 @@ class Controller(controller.BaseController):
|
||||
version_patch_meta = self.get_version_patch_meta_or_404(req, id)
|
||||
return {'version_patch_meta': version_patch_meta}
|
||||
|
||||
@utils.mutating
|
||||
def add_host_patch_history(self, req, version_patch_meta):
|
||||
"""
|
||||
Returns metadata about an patch history in the HTTP headers of the
|
||||
response object
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
:param id: The opaque version patch identifier
|
||||
|
||||
"""
|
||||
self._enforce(req, 'add_host_patch_history')
|
||||
patch_history_meta = \
|
||||
registry.add_host_patch_history_metadata(req.context,
|
||||
version_patch_meta)
|
||||
return {'patch_history_meta': patch_history_meta}
|
||||
|
||||
@utils.mutating
|
||||
def list_host_patch_history(self, req):
|
||||
"""
|
||||
Returns metadata about an patch history in the HTTP headers of the
|
||||
response object
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
:param id: The opaque version patch identifier
|
||||
|
||||
:raises HTTPNotFound if version patch metadata is not available to user
|
||||
"""
|
||||
self._enforce(req, 'get_host_patch_history')
|
||||
params = self._get_query_params(req)
|
||||
try:
|
||||
patch_history_meta = registry.list_host_patch_history_metadata(
|
||||
req.context, **params)
|
||||
except Exception:
|
||||
msg = "host patch history list error"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
return dict(patch_history_meta=patch_history_meta)
|
||||
|
||||
@utils.mutating
|
||||
def update_version_patch(self, req, id, version_patch_meta):
|
||||
"""
|
||||
@ -257,6 +295,9 @@ class VersionPatchDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def add_version_patch(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
def add_host_patch_history(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
def update_version_patch(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
@ -274,6 +315,13 @@ class VersionPatchserializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(version_patch=version_patch_meta))
|
||||
return response
|
||||
|
||||
def add_host_patch_history(self, response, result):
|
||||
version_patch_meta = result['patch_history_meta']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(patch_history=version_patch_meta))
|
||||
return response
|
||||
|
||||
def delete_version_patch(self, response, result):
|
||||
version_patch_meta = result['version_patch_meta']
|
||||
response.status = 201
|
||||
@ -288,6 +336,13 @@ class VersionPatchserializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(version_patch=version_patch_meta))
|
||||
return response
|
||||
|
||||
def list_host_patch_history(self, response, result):
|
||||
history_meta = result['patch_history_meta']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(patch_history=history_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""versions resource factory method"""
|
||||
|
124
code/daisy/daisy/db/sqlalchemy/api.py
Normal file → Executable file
124
code/daisy/daisy/db/sqlalchemy/api.py
Normal file → Executable file
@ -5898,6 +5898,121 @@ def _version_patch_update(context, values, version_patch_id):
|
||||
|
||||
return version_patch_get(context, version_patch_ref.id)
|
||||
|
||||
@retry(retry_on_exception=_retry_on_deadlock, wait_fixed=500,
|
||||
stop_max_attempt_number=50)
|
||||
def add_host_patch_history(context, values):
|
||||
"""add version to daisy."""
|
||||
return _host_patch_history_update(context, values, None)
|
||||
|
||||
def _host_patch_history_update(context, values, patch_history_id):
|
||||
"""update or add patch history to daisy."""
|
||||
values = values.copy()
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
if patch_history_id:
|
||||
patch_history_ref = _patch_history_get(context, patch_history_id,
|
||||
session=session)
|
||||
else:
|
||||
patch_history_ref = models.HostPatchHistory()
|
||||
|
||||
if patch_history_id:
|
||||
# Don't drop created_at if we're passing it in...
|
||||
_drop_protected_attrs(models.HostPatchHistory, values)
|
||||
# NOTE(iccha-sethi): updated_at must be explicitly set in case
|
||||
# only ImageProperty table was modifited
|
||||
values['updated_at'] = timeutils.utcnow()
|
||||
|
||||
if patch_history_id:
|
||||
if values.get('id', None): del values['id']
|
||||
patch_history_ref.update(values)
|
||||
_update_values(patch_history_ref, values)
|
||||
try:
|
||||
patch_history_ref.save(session=session)
|
||||
except db_exception.DBDuplicateEntry:
|
||||
raise exception.Duplicate("version patch ID %s already exists!"
|
||||
% values['id'])
|
||||
else:
|
||||
patch_history_ref.update(values)
|
||||
_update_values(patch_history_ref, values)
|
||||
try:
|
||||
patch_history_ref.save(session=session)
|
||||
except db_exception.DBDuplicateEntry:
|
||||
raise exception.Duplicate("version patch ID %s already exists!"
|
||||
% values['id'])
|
||||
return patch_history_get(context, patch_history_ref.id)
|
||||
|
||||
def _patch_history_get(context, id, session=None,
|
||||
force_show_deleted=False):
|
||||
"""Get an patch history or raise if it does not exist."""
|
||||
|
||||
session = session or get_session()
|
||||
try:
|
||||
query = session.query(models.HostPatchHistory).filter_by(
|
||||
id=id)
|
||||
|
||||
# filter out deleted images if context disallows it
|
||||
if not force_show_deleted and not context.can_see_deleted:
|
||||
query = query.filter_by(deleted=False)
|
||||
patch_history = query.one()
|
||||
return patch_history
|
||||
except sa_orm.exc.NoResultFound:
|
||||
msg = "No patch history patch found with ID %s" % id
|
||||
LOG.debug(msg)
|
||||
raise exception.NotFound(msg)
|
||||
|
||||
|
||||
def patch_history_get(context, id, session=None,
|
||||
force_show_deleted=False):
|
||||
patch_history = _patch_history_get(context, id,
|
||||
session=session,
|
||||
force_show_deleted=force_show_deleted)
|
||||
return patch_history
|
||||
|
||||
def list_host_patch_history(context, filters=None, marker=None, limit=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
sort_key = ['created_at'] if not sort_key else sort_key
|
||||
|
||||
default_sort_dir = 'desc'
|
||||
|
||||
if not sort_dir:
|
||||
sort_dir = [default_sort_dir] * len(sort_key)
|
||||
elif len(sort_dir) == 1:
|
||||
default_sort_dir = sort_dir[0]
|
||||
sort_dir *= len(sort_key)
|
||||
|
||||
filters = filters or {}
|
||||
|
||||
showing_deleted = False
|
||||
for key in ['created_at', 'id']:
|
||||
if key not in sort_key:
|
||||
sort_key.append(key)
|
||||
sort_dir.append(default_sort_dir)
|
||||
|
||||
session = get_session()
|
||||
query = session.query(models.HostPatchHistory).filter_by(deleted=showing_deleted)
|
||||
if 'host_id' in filters and 'version_id' in filters:
|
||||
host_id = filters.pop('host_id')
|
||||
version_id = filters.pop('version_id')
|
||||
query = session.query(models.HostPatchHistory).\
|
||||
filter_by(deleted=False).filter_by(host_id=host_id).\
|
||||
filter_by(version_id=version_id)
|
||||
if 'host_id' in filters:
|
||||
host_id = filters.pop('host_id')
|
||||
query = session.query(models.HostPatchHistory).\
|
||||
filter_by(deleted=False).filter_by(host_id=host_id)
|
||||
if 'type' in filters:
|
||||
type = filters.pop('type')
|
||||
query = session.query(models.HostPatchHistory).\
|
||||
filter_by(deleted=False).filter_by(type=type)
|
||||
patchs = []
|
||||
for patch_history in query.all():
|
||||
patch = patch_history.to_dict()
|
||||
version_ref = _version_get(context, patch['version_id'])
|
||||
if version_ref:
|
||||
patch['version_name'] = version_ref.name
|
||||
patchs.append(patch)
|
||||
return patchs
|
||||
|
||||
def _version_patch_get(context, version_patch_id, session=None,
|
||||
force_show_deleted=False):
|
||||
"""Get an version patch or raise if it does not exist."""
|
||||
@ -5990,8 +6105,13 @@ def version_patch_get_all(context, filters=None, marker=None, limit=None,
|
||||
version_patchs = []
|
||||
for version_patch in query.all():
|
||||
version_dict = version_patch.to_dict()
|
||||
version_sql = "select * from hosts where (hosts.version_patch_id ='"\
|
||||
+ version_dict['id'] + "' and hosts.deleted=0)"
|
||||
version_sql = "select * from hosts, host_patch_history where" \
|
||||
" (hosts.version_patch_id ='" + version_dict['id'] +\
|
||||
"' and hosts.deleted=0) or (hosts.id =" \
|
||||
"host_patch_history.host_id and " \
|
||||
"host_patch_history.patch_name='" + \
|
||||
version_dict['name'] +"' and hosts.deleted=0 and " \
|
||||
"host_patch_history.deleted=0)"
|
||||
hosts_number = session.execute(version_sql).fetchone()
|
||||
if hosts_number:
|
||||
version_dict['status'] = "used"
|
||||
|
@ -0,0 +1,58 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 sqlalchemy.schema import (Column, MetaData, Table)
|
||||
from daisy.db.sqlalchemy.migrate_repo.schema import (Boolean, DateTime,
|
||||
String, create_tables,
|
||||
drop_tables)
|
||||
|
||||
|
||||
def define_host_patch_history_table(meta):
|
||||
host_patch_history = Table('host_patch_history',
|
||||
meta,
|
||||
Column('id', String(36),
|
||||
primary_key=True,
|
||||
nullable=False),
|
||||
Column('host_id', String(36), nullable=False),
|
||||
Column('type', String(30), nullable=False),
|
||||
Column('version_id', String(36)),
|
||||
Column('patch_name', String(255)),
|
||||
Column('created_at', DateTime(),
|
||||
nullable=False),
|
||||
Column('updated_at', DateTime(),
|
||||
nullable=False),
|
||||
Column('deleted_at', DateTime()),
|
||||
Column('deleted',
|
||||
Boolean(),
|
||||
nullable=False,
|
||||
default=False,
|
||||
index=True),
|
||||
mysql_engine='InnoDB',
|
||||
extend_existing=True)
|
||||
return host_patch_history
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
tables = [define_host_patch_history_table(meta)]
|
||||
create_tables(tables)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
tables = [define_host_patch_history_table(meta)]
|
||||
drop_tables(tables)
|
@ -764,6 +764,18 @@ class ConfigService(BASE, DaisyBase):
|
||||
nullable=False)
|
||||
|
||||
|
||||
class HostPatchHistory(BASE, DaisyBase):
|
||||
|
||||
"""Represents an component config in the datastore."""
|
||||
__tablename__ = 'host_patch_history'
|
||||
__table_args__ = (Index('ix_host_patch_history_deleted', 'deleted'),)
|
||||
|
||||
host_id = Column(String(36), nullable=False)
|
||||
type = Column(String(30), nullable=False)
|
||||
version_id = Column(String(36), nullable=False)
|
||||
patch_name = Column(String(255), nullable=False)
|
||||
|
||||
|
||||
def register_models(engine):
|
||||
"""Create database tables for all models with the given engine."""
|
||||
models = (Hwm, Host, DiscoverHost, Cluster, ClusterHost, Template,
|
||||
@ -774,7 +786,8 @@ def register_models(engine):
|
||||
Subnet, FloatIpRange, DnsNameservers, Router, ServiceDisk,
|
||||
CinderVolume, OpticalSwitch, Version, VersionPatch,
|
||||
TemplateConfig, TemplateFunc, TemplateFuncConfigs,
|
||||
TemplateService, ConfigService, NeutronBackend)
|
||||
TemplateService, ConfigService, NeutronBackend,
|
||||
HostPatchHistory)
|
||||
for model in models:
|
||||
model.metadata.create_all(engine)
|
||||
|
||||
@ -789,6 +802,7 @@ def unregister_models(engine):
|
||||
Subnet, FloatIpRange, DnsNameservers, Router, ServiceDisk,
|
||||
CinderVolume, OpticalSwitch, Version, VersionPatch,
|
||||
TemplateConfig, TemplateFunc, TemplateFuncConfigs,
|
||||
TemplateService, ConfigService, NeutronBackend)
|
||||
TemplateService, ConfigService, NeutronBackend,
|
||||
HostPatchHistory)
|
||||
for model in models:
|
||||
model.metadata.drop_all(engine)
|
||||
|
@ -547,6 +547,14 @@ def init(mapper):
|
||||
controller=version_patch_resource,
|
||||
action='get_version_patch',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/patch_history",
|
||||
controller=version_patch_resource,
|
||||
action='add_host_patch_history',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect("/patch_history/list",
|
||||
controller=version_patch_resource,
|
||||
action='list_patch_history',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
template_configs_resource = template_configs.create_resource()
|
||||
mapper.connect("/import_template_configs",
|
||||
|
63
code/daisy/daisy/registry/api/v1/version_patchs.py
Normal file → Executable file
63
code/daisy/daisy/registry/api/v1/version_patchs.py
Normal file → Executable file
@ -42,7 +42,8 @@ DISPLAY_FIELDS_IN_INDEX = ['id', 'name', 'size',
|
||||
'version_id', 'container_format',
|
||||
'checksum']
|
||||
|
||||
SUPPORTED_FILTERS = ['name', 'status', 'version_id',
|
||||
SUPPORTED_FILTERS = ['name', 'status', 'version_id', 'host_id',
|
||||
'patch_name', 'version_name', 'version_id',
|
||||
'changes-since', 'protected', 'type']
|
||||
|
||||
SUPPORTED_SORT_KEYS = ('name', 'status', 'version_id', 'disk_format',
|
||||
@ -179,6 +180,26 @@ class Controller(object):
|
||||
return None
|
||||
return strutils.bool_from_string(deleted)
|
||||
|
||||
def _list_patch_history(self, context, filters, **params):
|
||||
"""Get patch history, wrapping in exception if necessary."""
|
||||
try:
|
||||
return self.db_api.list_host_patch_history(context,
|
||||
filters=filters,
|
||||
**params)
|
||||
except exception.NotFound:
|
||||
LOG.warn(_LW("Invalid marker patch history %(id)s could not be "
|
||||
"found.") % {'id': params.get('marker')})
|
||||
msg = _("Invalid marker. Host could not be found.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
except exception.Forbidden:
|
||||
LOG.warn(_LW("Access denied to patch history %(id)s but returning "
|
||||
"'not found'") % {'id': params.get('marker')})
|
||||
msg = _("Invalid marker. Host could not be found.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
except Exception:
|
||||
LOG.exception(_LE("Unable to get patch history"))
|
||||
raise
|
||||
|
||||
@utils.mutating
|
||||
def add_version_patch(self, req, body):
|
||||
"""Registers a new version with the registry.
|
||||
@ -337,6 +358,46 @@ class Controller(object):
|
||||
% version_patch_id)
|
||||
raise
|
||||
|
||||
@utils.mutating
|
||||
def list_patch_history(self, req):
|
||||
"""Return data about the given patch_history."""
|
||||
params = self._get_query_params(req)
|
||||
patch_history = self._list_patch_history(req.context, **params)
|
||||
return dict(patch_history=patch_history)
|
||||
|
||||
@utils.mutating
|
||||
def add_host_patch_history(self, req, body):
|
||||
"""Registers a new version with the registry.
|
||||
|
||||
:param req: wsgi Request object
|
||||
:param body: Dictionary of information about the version
|
||||
|
||||
:retval Returns the newly-created version information as a mapping,
|
||||
which will include the newly-created version's internal id
|
||||
in the 'id' field
|
||||
"""
|
||||
|
||||
patch_history_meta = body["patch_history"]
|
||||
try:
|
||||
patch_history = self.db_api.add_host_patch_history(
|
||||
req.context, patch_history_meta)
|
||||
version_data = dict(patch_history=patch_history)
|
||||
return version_data
|
||||
except exception.Duplicate:
|
||||
msg = (_("patch history with identifier %s already exists!") %
|
||||
patch_history_meta['patch_name'])
|
||||
LOG.warn(msg)
|
||||
return exc.HTTPConflict(msg)
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to add patch history metadata. "
|
||||
"Got error: %s") % utils.exception_to_str(e))
|
||||
LOG.error(msg)
|
||||
return exc.HTTPBadRequest(msg)
|
||||
except Exception:
|
||||
LOG.exception(_LE("Unable to create patch history %s"),
|
||||
patch_history_meta['patch_name'])
|
||||
raise
|
||||
|
||||
|
||||
def _limit_locations(image):
|
||||
locations = image.pop('locations', [])
|
||||
|
@ -719,6 +719,16 @@ def add_version_patch_metadata(context, version_patch_meta):
|
||||
return c.add_version_patch(version_patch_meta)
|
||||
|
||||
|
||||
def add_host_patch_history_metadata(context, patch_history_meta):
|
||||
c = get_registry_client(context)
|
||||
return c.add_host_patch_history(patch_history_meta)
|
||||
|
||||
|
||||
def list_host_patch_history_metadata(context, **kwargs):
|
||||
c = get_registry_client(context)
|
||||
return c.list_host_patch_history(**kwargs)
|
||||
|
||||
|
||||
def delete_version_patch_metadata(context, version_patch_id):
|
||||
LOG.debug("Deleting version metadata %s...", version_patch_id)
|
||||
c = get_registry_client(context)
|
||||
|
@ -32,6 +32,7 @@ from daisy.registry.api.v1 import networks
|
||||
from daisy.registry.api.v1 import template
|
||||
from daisy.registry.api.v1 import hwms
|
||||
from daisy.registry.api.v1 import versions
|
||||
from daisy.registry.api.v1 import version_patchs
|
||||
from daisy.registry.api.v1 import disk_array
|
||||
from daisy.registry.api.v1 import template_configs
|
||||
from daisy.registry.api.v1 import template_funcs
|
||||
@ -1428,6 +1429,31 @@ class RegistryClient(BaseClient):
|
||||
data = jsonutils.loads(res.read())['version_patch']
|
||||
return data
|
||||
|
||||
def add_host_patch_history(self, patch_history_metadata):
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
if 'patch_history' not in patch_history_metadata:
|
||||
patch_history_metadata = dict(patch_history=patch_history_metadata)
|
||||
|
||||
body = jsonutils.dumps(patch_history_metadata)
|
||||
|
||||
res = self.do_request(
|
||||
"POST",
|
||||
"/patch_history",
|
||||
body=body,
|
||||
headers=headers)
|
||||
data = jsonutils.loads(res.read())
|
||||
return data['patch_history']
|
||||
|
||||
def list_host_patch_history(self, **kwargs):
|
||||
"""Return a list of version patch associations from Registry."""
|
||||
params = self._extract_params(kwargs, version_patchs.SUPPORTED_PARAMS)
|
||||
res = self.do_request("GET", "/patch_history/list", params=params)
|
||||
version_list = jsonutils.loads(res.read())['patch_history']
|
||||
return version_list
|
||||
|
||||
def get_template_config(self, template_config_id):
|
||||
"""Return a list of template config associations from Registry."""
|
||||
res = self.do_request("GET", "/template_configs/%s" %
|
||||
|
@ -409,6 +409,31 @@ class TestOsInstall(test.TestCase):
|
||||
install.upgrade_os(req, version_id, version_patch_id, update_file,
|
||||
hosts_list, update_object)
|
||||
|
||||
@mock.patch('daisy.api.backends.common.update_db_host_status')
|
||||
@mock.patch("daisy.api.backends.common.get_host_detail")
|
||||
@mock.patch('daisy.api.backends.osinstall.pxe.install.'
|
||||
'os_thread_bin')
|
||||
@mock.patch('daisy.registry.client.v1.api.add_host_patch_history_metadata')
|
||||
def test_upgrade_os_patch_active(self, mock_patch_history,
|
||||
mock_os_thread_in,
|
||||
mock_get_host_detail,
|
||||
mock_do_update_db_status):
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True, user='fake user',
|
||||
tenant='fake tenant')
|
||||
version_id = "1"
|
||||
version_patch_id = "123"
|
||||
update_file = "test"
|
||||
hosts_list = [{'10.43.177.1': {'id': "1"}}]
|
||||
update_object = "vplat"
|
||||
mock_do_update_db_status.return_value = {}
|
||||
mock_patch_history.return_value = {}
|
||||
mock_get_host_detail.return_value = {'os_status': 'active'}
|
||||
mock_os_thread_in.return_value = {}
|
||||
install.upgrade_os(req, version_id, version_patch_id, update_file,
|
||||
hosts_list, update_object)
|
||||
self.assertEqual(1, mock_patch_history.call_count)
|
||||
|
||||
@mock.patch('subprocess.check_output')
|
||||
def test_exec_upgrade_with_vplat(self, mock_check_output):
|
||||
host_ip = '127.0.0.1'
|
||||
|
209
code/daisy/daisy/tests/api/test_version_patchs.py
Executable file
209
code/daisy/daisy/tests/api/test_version_patchs.py
Executable file
@ -0,0 +1,209 @@
|
||||
import mock
|
||||
import webob
|
||||
import json as jsonutils
|
||||
from daisy.api.v1 import version_patchs
|
||||
from daisy.context import RequestContext
|
||||
from daisy import test
|
||||
|
||||
|
||||
def set_version_meta():
|
||||
version_patch_meta = {}
|
||||
version_patch_meta["name"] = "test_version"
|
||||
version_patch_meta["description"] = "111"
|
||||
version_patch_meta["status"] = "used"
|
||||
return version_patch_meta
|
||||
|
||||
|
||||
class TestVersionsPatchApiConfig(test.TestCase):
|
||||
def setUp(self):
|
||||
super(TestVersionsPatchApiConfig, self).setUp()
|
||||
self.controller = version_patchs.Controller()
|
||||
|
||||
@mock.patch('daisy.registry.client.v1.client.RegistryClient.'
|
||||
'do_request')
|
||||
def test_add_version_patch(self, mock_do_request):
|
||||
version_patch_meta = set_version_meta()
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
|
||||
def fake_do_request(method, path, **params):
|
||||
res = mock.Mock()
|
||||
if method == 'POST':
|
||||
post_result = {
|
||||
u'version_patch': {u'status': u'used',
|
||||
u'name': u'name3',
|
||||
u'deleted': False, u'checksum': None,
|
||||
u'created_at': u'2016-07-12',
|
||||
u'description': None,
|
||||
u'status': u'used',
|
||||
u'deleted_at': None,
|
||||
u'size': None}}
|
||||
res.read.return_value = jsonutils.dumps(post_result)
|
||||
return res
|
||||
|
||||
mock_do_request.side_effect = fake_do_request
|
||||
add_version = self.controller.add_version_patch(req,
|
||||
version_patch_meta)
|
||||
self.assertEqual("name3",
|
||||
add_version['version_patch_meta']['name'])
|
||||
|
||||
def test_add_version_patch_with_no_name(self):
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
version_meta = {}
|
||||
version_meta["description"] = "111"
|
||||
self.assertRaises(ValueError, self.controller.add_version_patch, req,
|
||||
version_meta)
|
||||
|
||||
@mock.patch('daisy.registry.client.v1.client.RegistryClient.'
|
||||
'do_request')
|
||||
def test_update_version_patch(self, mock_do_request):
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
|
||||
def fake_do_request(method, path, **params):
|
||||
res = mock.Mock()
|
||||
if method == "GET":
|
||||
get_result = {
|
||||
"version_patch": {"status": "unused",
|
||||
"name": "ssh2.exe",
|
||||
"checksum": "60489112c272fbf",
|
||||
"size": 1089536,
|
||||
"id": "1",
|
||||
"description": "1",
|
||||
"deleted": 0}}
|
||||
res.read.return_value = jsonutils.dumps(get_result)
|
||||
return res
|
||||
elif method == 'PUT':
|
||||
post_result = {
|
||||
u'version_patch': {u'status': u'unused',
|
||||
u'name': u'test',
|
||||
u'deleted': 0,
|
||||
u'checksum': None,
|
||||
u'description': None,
|
||||
u'deleted_at': None,
|
||||
u'size': None}}
|
||||
res.read.return_value = jsonutils.dumps(post_result)
|
||||
return res
|
||||
|
||||
mock_do_request.side_effect = fake_do_request
|
||||
|
||||
version_patch = {}
|
||||
version_patch["name"] = "test"
|
||||
version_patch["description"] = "111"
|
||||
version_patch_id = "1"
|
||||
add_version = self.controller.update_version_patch(req,
|
||||
version_patch_id,
|
||||
version_patch)
|
||||
self.assertEqual("test",
|
||||
add_version['version_patch_meta']['name'])
|
||||
|
||||
@mock.patch('daisy.registry.client.v1.client.RegistryClient.'
|
||||
'do_request')
|
||||
def test_get_version_patch(self, mock_do_request):
|
||||
version_patch_id = "34811a0e66792a979e99"
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
|
||||
def fake_do_request(method, path, **params):
|
||||
res = mock.Mock()
|
||||
if method == "GET":
|
||||
get_result = {
|
||||
"version_patch": {"status": "unused",
|
||||
"name": "ssh2.exe",
|
||||
"checksum": "60489112c2c0862fbf",
|
||||
"size": 1089536,
|
||||
"id": "34811a0e66792a979e99",
|
||||
"description": "azsdadsad"}}
|
||||
res.read.return_value = jsonutils.dumps(get_result)
|
||||
return res
|
||||
|
||||
mock_do_request.side_effect = fake_do_request
|
||||
version = self.controller.get_version_patch(req, version_patch_id)
|
||||
self.assertEqual(version_patch_id,
|
||||
version['version_patch_meta']['id'])
|
||||
|
||||
@mock.patch('daisy.registry.client.v1.client.RegistryClient.'
|
||||
'do_request')
|
||||
def test_delete_version_patch(self, mock_do_request):
|
||||
version_patch_id = "34811a0e-a69f-4dd3-bbfb-66792a979e99"
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
|
||||
def fake_do_request(method, path, **params):
|
||||
res = mock.Mock()
|
||||
if method == "GET":
|
||||
get_result = {
|
||||
"version_patch": {"status": "unused",
|
||||
"name": "ssh2.exe",
|
||||
"checksum": "60489112c277862fbf",
|
||||
"size": 1089536,
|
||||
"id": "34811a0e-a69f-2a979e99",
|
||||
"description": "azsad"}}
|
||||
res.read.return_value = jsonutils.dumps(get_result)
|
||||
return res
|
||||
elif method == "DELETE":
|
||||
result = {
|
||||
"version_patch": {"status": "unused",
|
||||
"name": "ssh2.exe",
|
||||
"checksum": "60489112c277a18147b",
|
||||
"created_at": "2016-07-12",
|
||||
"size": 1089536,
|
||||
"updated_at": "2016-07-12",
|
||||
"id": "34811a0e-a69f-4dd3",
|
||||
"description": "azsdadsad"}}
|
||||
res.read.return_value = jsonutils.dumps(result)
|
||||
return res
|
||||
|
||||
mock_do_request.side_effect = fake_do_request
|
||||
version = self.controller.delete_version_patch(req, version_patch_id)
|
||||
self.assertEqual(200, version.status_code)
|
||||
|
||||
@mock.patch('daisy.registry.client.v1.api.'
|
||||
'add_host_patch_history_metadata')
|
||||
def test_add_host_patch_history(self, mock_add_history):
|
||||
history_meta = {'patch_name': 'test'}
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
|
||||
mock_add_history.return_value = history_meta
|
||||
add_history = self.controller.add_host_patch_history(req, history_meta)
|
||||
self.assertEqual({'patch_history_meta': history_meta}, add_history)
|
||||
|
||||
@mock.patch('daisy.registry.client.v1.api.'
|
||||
'list_host_patch_history_metadata')
|
||||
def test_list_host_patch_history(self, mock_list_history):
|
||||
history_meta = {'patch_name': 'test'}
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
mock_list_history.return_value = history_meta
|
||||
historys = self.controller.list_host_patch_history(req)
|
||||
self.assertEqual({'patch_history_meta': history_meta}, historys)
|
||||
|
||||
@mock.patch('daisy.registry.client.v1.api.'
|
||||
'list_host_patch_history_metadata')
|
||||
def test_list_host_patch_history_with_except(self, mock_list_history):
|
||||
def mock_history(*args, **kwargs):
|
||||
raise webob.exc.HTTPBadRequest
|
||||
|
||||
req = webob.Request.blank('/')
|
||||
req.context = RequestContext(is_admin=True,
|
||||
user='fake user',
|
||||
tenant='fake tenamet')
|
||||
mock_list_history.side_effect = mock_history
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.list_host_patch_history, req)
|
@ -3,6 +3,7 @@ from daisy.context import RequestContext
|
||||
from daisy.db.sqlalchemy import api
|
||||
from daisy import test
|
||||
from daisy.tests import test_utils
|
||||
from daisy.db.sqlalchemy import models
|
||||
import mock
|
||||
from oslo_db.sqlalchemy import session
|
||||
from oslo_db.sqlalchemy.session import Query
|
||||
@ -759,7 +760,6 @@ class TestSqlalchemyApi(test.TestCase):
|
||||
|
||||
user = User(id='1', status='used')
|
||||
mock_qry_all.return_value = [user]
|
||||
#Query.all = mock.Mock(return_value=[user])
|
||||
session.query = mock.Mock(return_value=version_values)
|
||||
versions = api.version_get_all(self.req.context,
|
||||
filters=filters_value,
|
||||
@ -768,6 +768,110 @@ class TestSqlalchemyApi(test.TestCase):
|
||||
sort_dir=sort_dir_value)
|
||||
self.assertEqual(version_values['id'], versions[0]['id'])
|
||||
|
||||
@mock.patch("oslo_db.sqlalchemy.session.Query.all")
|
||||
@mock.patch('daisy.db.sqlalchemy.api.get_session')
|
||||
@mock.patch('daisy.db.sqlalchemy.api._version_get')
|
||||
def test_list_host_patch_history(self, mock_version_get,
|
||||
mock_do_sesison,
|
||||
mock_qry_all):
|
||||
def mock_sesison(*args, **kwargs):
|
||||
return FakeSession()
|
||||
|
||||
class User(object):
|
||||
def __init__(self, version_id, name):
|
||||
self.version_id = version_id
|
||||
self.name = name
|
||||
|
||||
def to_dict(self):
|
||||
return {'version_id': self.version_id}
|
||||
|
||||
filters_value = {
|
||||
'deleted': False,
|
||||
'host_id': u'a0ed9c30-afd3-4bba'}
|
||||
limit_value = 25
|
||||
sort_key_value = ['created_at']
|
||||
sort_dir_value = ['desc']
|
||||
mock_do_sesison.side_effect = mock_sesison
|
||||
user = User(version_id='1', name='test')
|
||||
mock_qry_all.return_value = [user]
|
||||
mock_version_get.return_value = user
|
||||
history = api.list_host_patch_history(self.req.context,
|
||||
filters=filters_value,
|
||||
limit=limit_value,
|
||||
sort_key=sort_key_value,
|
||||
sort_dir=sort_dir_value)
|
||||
self.assertEqual('1', history[0]['version_id'])
|
||||
|
||||
@mock.patch("oslo_db.sqlalchemy.session.Query.one")
|
||||
@mock.patch('daisy.db.sqlalchemy.api.get_session')
|
||||
def test__patch_history_get(self, mock_do_sesison, mock_qry_one):
|
||||
def mock_sesison(*args, **kwargs):
|
||||
return FakeSession()
|
||||
|
||||
id = "1"
|
||||
mock_qry_one.return_value = {}
|
||||
mock_do_sesison.side_effect = mock_sesison
|
||||
history = api._patch_history_get(self.req.context, id,
|
||||
force_show_deleted=True)
|
||||
self.assertEqual({}, history)
|
||||
|
||||
@mock.patch('daisy.db.sqlalchemy.api._patch_history_get')
|
||||
def test_patch_history_get(self, mock_patch_get):
|
||||
mock_patch_get.return_value = '1'
|
||||
history = api._patch_history_get(self.req.context, id,
|
||||
force_show_deleted=True)
|
||||
self.assertEqual('1', history)
|
||||
|
||||
@mock.patch('daisy.db.sqlalchemy.api.get_session')
|
||||
@mock.patch('daisy.db.sqlalchemy.api._patch_history_get')
|
||||
@mock.patch('daisy.db.sqlalchemy.models.HostPatchHistory.save')
|
||||
@mock.patch('daisy.db.sqlalchemy.models.HostPatchHistory.update')
|
||||
@mock.patch('daisy.db.sqlalchemy.api._update_values')
|
||||
def test_host_patch_history_update_with_id(self, mock_values,
|
||||
mock_update,
|
||||
mock_save,
|
||||
mock_patch_get,
|
||||
mock_do_sesison):
|
||||
def mock_sesison(*args, **kwargs):
|
||||
return FakeSession()
|
||||
|
||||
mock_values.return_value = None
|
||||
mock_do_sesison.side_effect = mock_sesison
|
||||
mock_save.return_value = None
|
||||
mock_update.return_value = {'host_id': '2', 'patch_name': '3'}
|
||||
mock_patch_get.return_value = models.HostPatchHistory()
|
||||
patch_history_id = '123'
|
||||
values = {'patch_name': '3', 'host_id': '2'}
|
||||
api._host_patch_history_update(self.req.context,
|
||||
values, patch_history_id)
|
||||
self.assertTrue(mock_save.called)
|
||||
|
||||
@mock.patch('daisy.db.sqlalchemy.api.get_session')
|
||||
@mock.patch('daisy.db.sqlalchemy.api._patch_history_get')
|
||||
@mock.patch('daisy.db.sqlalchemy.models.HostPatchHistory.save')
|
||||
def test_host_patch_history_update_with_no_id(self, mock_save,
|
||||
mock_patch_get,
|
||||
mock_do_sesison):
|
||||
def mock_sesison(*args, **kwargs):
|
||||
return FakeSession()
|
||||
|
||||
mock_do_sesison.side_effect = mock_sesison
|
||||
mock_save.return_value = None
|
||||
mock_patch_get.return_value = None
|
||||
patch_history_id = ''
|
||||
values = {'patch_name': 'test2', 'host_id': '123'}
|
||||
api._host_patch_history_update(self.req.context,
|
||||
values, patch_history_id)
|
||||
self.assertTrue(mock_save.called)
|
||||
|
||||
@mock.patch('daisy.db.sqlalchemy.api._host_patch_history_update')
|
||||
def test_add_host_patch_history(self, mock_history_update):
|
||||
values = {'patch_name': 'test2', 'host_id': '123'}
|
||||
mock_history_update.return_value = None
|
||||
api.add_host_patch_history(self.req.context,
|
||||
values)
|
||||
self.assertTrue(mock_history_update.called)
|
||||
|
||||
def test_get_host_interface_vf_info(self):
|
||||
self.assertRaises(exception.NotFound,
|
||||
api._get_host_interface_vf_info,
|
||||
|
36
code/daisy/daisy/tests/registry/api/test_version_patchs.py
Executable file
36
code/daisy/daisy/tests/registry/api/test_version_patchs.py
Executable file
@ -0,0 +1,36 @@
|
||||
import mock
|
||||
from daisy import test
|
||||
import webob
|
||||
from daisy.context import RequestContext
|
||||
from daisy.common import exception
|
||||
from daisy.registry.api.v1 import version_patchs
|
||||
|
||||
|
||||
def fake_version_patch_add(host_id):
|
||||
if host_id == 'd134fa48-a':
|
||||
return exception.NotFound
|
||||
elif host_id == 'd134fa48-b':
|
||||
return exception.Forbidden
|
||||
elif host_id == 'd134fa48-c':
|
||||
return exception.Invalid
|
||||
|
||||
|
||||
class TestVersionpatchs(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVersionpatchs, self).setUp()
|
||||
self.controller = version_patchs.Controller()
|
||||
|
||||
@mock.patch('daisy.db.sqlalchemy.api.add_host_patch_history')
|
||||
def test_add_host_patch_history(self, mock_add_patch_history):
|
||||
self.req = webob.Request.blank('/')
|
||||
self.req.context = RequestContext(is_admin=True, user='fake user',
|
||||
tenant='fake tenant')
|
||||
host_id = 'd04cfa48'
|
||||
patch_name = 'd134fa'
|
||||
body = {"patch_history": {'host_id': host_id,
|
||||
'patch_name': patch_name}}
|
||||
mock_add_patch_history.return_value = {'host_id': host_id,
|
||||
'patch_name': patch_name}
|
||||
actual_data = self.controller.add_host_patch_history(self.req, body)
|
||||
self.assertEqual(body, actual_data)
|
@ -2574,6 +2574,61 @@ def do_version_patch_add(dc, args):
|
||||
_daisy_show(version)
|
||||
|
||||
|
||||
@utils.arg('--host-id', metavar='<HOST_ID>',
|
||||
help='name of version.')
|
||||
@utils.arg('--version-id', metavar='<VERSION>',
|
||||
help='version id')
|
||||
@utils.arg('--type', metavar='<TYPE>',
|
||||
help='type is tecs,vplat.....')
|
||||
@utils.arg('--patch-name', metavar='<PATCH>',
|
||||
help='patch name')
|
||||
def do_host_patch_history_add(dc, args):
|
||||
"""Add a host patch history."""
|
||||
|
||||
fields = dict(filter(lambda x: x[1] is not None, vars(args).items()))
|
||||
|
||||
# Filter out values we can't use
|
||||
CREATE_PARAMS = daisyclient.v1.version_patchs.CREATE_PARAMS
|
||||
fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items()))
|
||||
patch_history = dc.version_patchs.add_host_patch_history(**fields)
|
||||
_daisy_show(patch_history)
|
||||
|
||||
|
||||
@utils.arg('--host-id', metavar='<HOST>',
|
||||
help='Filter patch history with host id.')
|
||||
@utils.arg('--type', metavar='<type>',
|
||||
help='Filter by type.')
|
||||
@utils.arg('--version-id', metavar='<version>',
|
||||
help='Filter by version number.')
|
||||
@utils.arg('--page-size', metavar='<SIZE>', default=None, type=int,
|
||||
help='Number to request in each paginated request.')
|
||||
@utils.arg('--sort-key', default='name',
|
||||
choices=daisyclient.v1.versions.SORT_KEY_VALUES,
|
||||
help='Sort version list by specified field.')
|
||||
@utils.arg('--sort-dir', default='asc',
|
||||
choices=daisyclient.v1.versions.SORT_DIR_VALUES,
|
||||
help='Sort version list in specified direction.')
|
||||
def do_patch_history_list(dc, args):
|
||||
"""List hosts you can access."""
|
||||
filter_keys = ['host_id', 'type', 'version_id']
|
||||
filter_items = [(key, getattr(args, key)) for key in filter_keys]
|
||||
filters = dict([item for item in filter_items if item[1] is not None])
|
||||
|
||||
kwargs = {'filters': filters}
|
||||
if args.page_size is not None:
|
||||
kwargs['page_size'] = args.page_size
|
||||
|
||||
kwargs['sort_key'] = args.sort_key
|
||||
kwargs['sort_dir'] = args.sort_dir
|
||||
|
||||
versions = dc.version_patchs.list_host_patch_history(**kwargs)
|
||||
|
||||
columns = ['ID', 'HOST_ID', 'TYPE', 'VERSION_ID', 'VERSION_NAME',
|
||||
'PATCH_NAME']
|
||||
|
||||
utils.print_list(versions, columns)
|
||||
|
||||
|
||||
@utils.arg('id', metavar='<ID>',
|
||||
help='ID of version patch.')
|
||||
@utils.arg('--name', metavar='<NAME>',
|
||||
|
@ -14,17 +14,16 @@
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_utils import strutils
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from daisyclient.common import utils
|
||||
from daisyclient.openstack.common.apiclient import base
|
||||
|
||||
CREATE_PARAMS = ('id', 'name', 'description', 'version_id',
|
||||
'size', 'checksum', 'status')
|
||||
'size', 'checksum', 'status', 'host_id',
|
||||
'patch_name', 'type')
|
||||
|
||||
|
||||
DEFAULT_PAGE_SIZE = 200
|
||||
@ -54,6 +53,16 @@ class VersionPatch(base.Resource):
|
||||
class VersionPatchManager(base.ManagerWithFind):
|
||||
resource_class = VersionPatch
|
||||
|
||||
def _list(self, url, response_key, obj_class=None, body=None):
|
||||
resp, body = self.client.get(url)
|
||||
|
||||
if obj_class is None:
|
||||
obj_class = self.resource_class
|
||||
|
||||
data = body[response_key]
|
||||
return ([obj_class(self, res, loaded=True) for res in data if res],
|
||||
resp)
|
||||
|
||||
def _version_meta_from_headers(self, headers):
|
||||
meta = {'properties': {}}
|
||||
safe_decode = encodeutils.safe_decode
|
||||
@ -130,8 +139,8 @@ class VersionPatchManager(base.ManagerWithFind):
|
||||
if sort_dir in SORT_DIR_VALUES:
|
||||
params['sort_dir'] = sort_dir
|
||||
else:
|
||||
raise ValueError('sort_dir must be one of the following: %s.'
|
||||
% ', '.join(SORT_DIR_VALUES))
|
||||
raise ValueError('sort_dir must be one of the following:'
|
||||
' %s.' % ', '.join(SORT_DIR_VALUES))
|
||||
|
||||
filters = parameters.get('filters', {})
|
||||
params.update(filters)
|
||||
@ -200,3 +209,90 @@ class VersionPatchManager(base.ManagerWithFind):
|
||||
|
||||
def list(self, **kwargs):
|
||||
return
|
||||
|
||||
def list_host_patch_history(self, **kwargs):
|
||||
absolute_limit = kwargs.get('limit')
|
||||
page_size = kwargs.get('page_size', DEFAULT_PAGE_SIZE)
|
||||
|
||||
def paginate(qp, return_request_id=None):
|
||||
for param, value in six.iteritems(qp):
|
||||
if isinstance(value, six.string_types):
|
||||
# Note(flaper87) Url encoding should
|
||||
# be moved inside http utils, at least
|
||||
# shouldn't be here.
|
||||
#
|
||||
# Making sure all params are str before
|
||||
# trying to encode them
|
||||
qp[param] = encodeutils.safe_decode(value)
|
||||
|
||||
url = '/v1/patch_history/list?%s' % urlparse.urlencode(qp)
|
||||
patchs_history, resp = self._list(url, "patch_history")
|
||||
|
||||
if return_request_id is not None:
|
||||
return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None))
|
||||
|
||||
for patch_history in patchs_history:
|
||||
yield patch_history
|
||||
|
||||
return_request_id = kwargs.get('return_req_id', None)
|
||||
|
||||
params = self._build_params(kwargs)
|
||||
|
||||
seen = 0
|
||||
while True:
|
||||
seen_last_page = 0
|
||||
filtered = 0
|
||||
for template_func in paginate(params, return_request_id):
|
||||
last_template_func = template_func.id
|
||||
|
||||
if (absolute_limit is not None and
|
||||
seen + seen_last_page >= absolute_limit):
|
||||
# Note(kragniz): we've seen enough images
|
||||
return
|
||||
else:
|
||||
seen_last_page += 1
|
||||
yield template_func
|
||||
|
||||
seen += seen_last_page
|
||||
|
||||
if seen_last_page + filtered == 0:
|
||||
# Note(kragniz): we didn't get any hosts in the last page
|
||||
return
|
||||
|
||||
if absolute_limit is not None and seen >= absolute_limit:
|
||||
# Note(kragniz): reached the limit of hosts to return
|
||||
return
|
||||
|
||||
if page_size and seen_last_page + filtered < page_size:
|
||||
# Note(kragniz): we've reached the last page of the hosts
|
||||
return
|
||||
|
||||
# Note(kragniz): there are more hosts to come
|
||||
params['marker'] = last_template_func
|
||||
seen_last_page = 0
|
||||
|
||||
def add_host_patch_history(self, **kwargs):
|
||||
"""Add a version
|
||||
TODO(bcwaldon): document accepted params
|
||||
"""
|
||||
fields = {}
|
||||
for field in kwargs:
|
||||
if field in CREATE_PARAMS:
|
||||
fields[field] = kwargs[field]
|
||||
elif field == 'return_req_id':
|
||||
continue
|
||||
else:
|
||||
msg = 'create() got an unexpected keyword argument \'%s\''
|
||||
raise TypeError(msg % field)
|
||||
|
||||
hdrs = self._version_meta_to_headers(fields)
|
||||
|
||||
resp, body = self.client.post('/v1/patch_history',
|
||||
headers=None,
|
||||
data=hdrs)
|
||||
return_request_id = kwargs.get('return_req_id', None)
|
||||
if return_request_id is not None:
|
||||
return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None))
|
||||
|
||||
return VersionPatch(self, self._format_version_meta_for_user(
|
||||
body['patch_history']))
|
||||
|
Loading…
Reference in New Issue
Block a user