
This reverts commit 35472d1f153fb20393c6d6fb6dffc1b83db5355b, reversing changes made to 5a929be775bb4513560b87f5da314e12421df665. Change-Id: Ie5f2f92473489bb5be981b97e17597e91ff1cbf9
1074 lines
32 KiB
Python
1074 lines
32 KiB
Python
# Copyright 2014 Huawei Technologies Co. Ltd
|
|
#
|
|
# 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.
|
|
|
|
"""Host database operations."""
|
|
import functools
|
|
import logging
|
|
import netaddr
|
|
import re
|
|
|
|
from compass.db.api import database
|
|
from compass.db.api import metadata_holder as metadata_api
|
|
from compass.db.api import permission
|
|
from compass.db.api import user as user_api
|
|
from compass.db.api import utils
|
|
from compass.db import exception
|
|
from compass.db import models
|
|
from compass.utils import util
|
|
|
|
|
|
SUPPORTED_FIELDS = ['name', 'os_name', 'owner', 'mac']
|
|
SUPPORTED_MACHINE_HOST_FIELDS = [
|
|
'mac', 'tag', 'location', 'os_name', 'os_id'
|
|
]
|
|
SUPPORTED_NETOWORK_FIELDS = [
|
|
'interface', 'ip', 'is_mgmt', 'is_promiscuous'
|
|
]
|
|
RESP_FIELDS = [
|
|
'id', 'name', 'hostname', 'os_name', 'owner', 'mac',
|
|
'switch_ip', 'port', 'switches', 'os_installer', 'os_id', 'ip',
|
|
'reinstall_os', 'os_installed', 'tag', 'location', 'networks',
|
|
'created_at', 'updated_at'
|
|
]
|
|
RESP_CLUSTER_FIELDS = [
|
|
'id', 'name', 'os_name', 'reinstall_distributed_system',
|
|
'owner', 'adapter_name', 'flavor_name',
|
|
'distributed_system_installed', 'created_at', 'updated_at'
|
|
]
|
|
RESP_NETWORK_FIELDS = [
|
|
'id', 'ip', 'interface', 'netmask', 'is_mgmt', 'is_promiscuous',
|
|
'created_at', 'updated_at'
|
|
]
|
|
RESP_CONFIG_FIELDS = [
|
|
'os_config',
|
|
'config_setp',
|
|
'config_validated',
|
|
'networks',
|
|
'created_at',
|
|
'updated_at'
|
|
]
|
|
RESP_DEPLOYED_CONFIG_FIELDS = [
|
|
'deployed_os_config'
|
|
]
|
|
RESP_DEPLOY_FIELDS = [
|
|
'status', 'host'
|
|
]
|
|
UPDATED_FIELDS = ['name', 'reinstall_os']
|
|
UPDATED_CONFIG_FIELDS = [
|
|
'put_os_config'
|
|
]
|
|
PATCHED_CONFIG_FIELDS = [
|
|
'patched_os_config'
|
|
]
|
|
UPDATED_DEPLOYED_CONFIG_FIELDS = [
|
|
'deployed_os_config'
|
|
]
|
|
ADDED_NETWORK_FIELDS = [
|
|
'interface', 'ip', 'subnet_id'
|
|
]
|
|
OPTIONAL_ADDED_NETWORK_FIELDS = ['is_mgmt', 'is_promiscuous']
|
|
UPDATED_NETWORK_FIELDS = [
|
|
'interface', 'ip', 'subnet_id', 'subnet', 'is_mgmt',
|
|
'is_promiscuous'
|
|
]
|
|
IGNORE_FIELDS = [
|
|
'id', 'created_at', 'updated_at'
|
|
]
|
|
RESP_STATE_FIELDS = [
|
|
'id', 'state', 'percentage', 'message', 'severity', 'ready'
|
|
]
|
|
UPDATED_STATE_FIELDS = [
|
|
'state', 'percentage', 'message', 'severity'
|
|
]
|
|
UPDATED_STATE_INTERNAL_FIELDS = [
|
|
'ready'
|
|
]
|
|
RESP_LOG_FIELDS = [
|
|
'id', 'filename', 'position', 'partial_line', 'percentage',
|
|
'message', 'severity', 'line_matcher_name'
|
|
]
|
|
ADDED_LOG_FIELDS = [
|
|
'filename'
|
|
]
|
|
UPDATED_LOG_FIELDS = [
|
|
'position', 'partial_line', 'percentage',
|
|
'message', 'severity', 'line_matcher_name'
|
|
]
|
|
|
|
|
|
@utils.supported_filters(optional_support_keys=SUPPORTED_FIELDS)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOSTS
|
|
)
|
|
@utils.wrap_to_dict(RESP_FIELDS)
|
|
def list_hosts(user=None, session=None, **filters):
|
|
"""List hosts."""
|
|
return utils.list_db_objects(
|
|
session, models.Host, **filters
|
|
)
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=SUPPORTED_MACHINE_HOST_FIELDS)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOSTS
|
|
)
|
|
@utils.output_filters(
|
|
missing_ok=True,
|
|
tag=utils.general_filter_callback,
|
|
location=utils.general_filter_callback,
|
|
os_name=utils.general_filter_callback,
|
|
os_id=utils.general_filter_callback
|
|
)
|
|
@utils.wrap_to_dict(RESP_FIELDS)
|
|
def list_machines_or_hosts(user=None, session=None, **filters):
|
|
"""List machines or hosts if possible."""
|
|
machines = utils.list_db_objects(
|
|
session, models.Machine, **filters
|
|
)
|
|
machines_or_hosts = []
|
|
for machine in machines:
|
|
host = machine.host
|
|
if host:
|
|
machines_or_hosts.append(host)
|
|
else:
|
|
machines_or_hosts.append(machine)
|
|
return machines_or_hosts
|
|
|
|
|
|
def _get_host(host_id, session=None, **kwargs):
|
|
"""Get host by id."""
|
|
if isinstance(host_id, (int, long)):
|
|
return utils.get_db_object(
|
|
session, models.Host,
|
|
id=host_id, **kwargs
|
|
)
|
|
else:
|
|
raise exception.InvalidParameter(
|
|
'host id %s type is not int compatible' % host_id
|
|
)
|
|
|
|
|
|
def get_host_internal(host_id, session=None, **kwargs):
|
|
"""Helper function to get host.
|
|
|
|
Used by other files under db/api.
|
|
"""
|
|
return _get_host(host_id, session=session, **kwargs)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOSTS
|
|
)
|
|
@utils.wrap_to_dict(RESP_FIELDS)
|
|
def get_host(
|
|
host_id, exception_when_missing=True,
|
|
user=None, session=None, **kwargs
|
|
):
|
|
"""get host info."""
|
|
return _get_host(
|
|
host_id,
|
|
exception_when_missing=exception_when_missing,
|
|
session=session
|
|
)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOSTS
|
|
)
|
|
@utils.wrap_to_dict(RESP_FIELDS)
|
|
def get_machine_or_host(
|
|
host_id, exception_when_missing=True,
|
|
user=None, session=None, **kwargs
|
|
):
|
|
"""get machine or host if possible."""
|
|
from compass.db.api import machine as machine_api
|
|
machine = machine_api.get_machine_internal(
|
|
host_id,
|
|
exception_when_missing=exception_when_missing,
|
|
session=session
|
|
)
|
|
if machine.host:
|
|
return machine.host
|
|
else:
|
|
return machine
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOST_CLUSTERS
|
|
)
|
|
@utils.wrap_to_dict(RESP_CLUSTER_FIELDS)
|
|
def get_host_clusters(host_id, user=None, session=None, **kwargs):
|
|
"""get host clusters."""
|
|
host = _get_host(host_id, session=session)
|
|
return [clusterhost.cluster for clusterhost in host.clusterhosts]
|
|
|
|
|
|
def check_host_validated(host):
|
|
"""Check host is validated."""
|
|
if not host.config_validated:
|
|
raise exception.Forbidden(
|
|
'host %s is not validated' % host.name
|
|
)
|
|
|
|
|
|
def check_host_editable(
|
|
host, user=None,
|
|
check_in_installing=False
|
|
):
|
|
"""Check host is editable.
|
|
|
|
If we try to set reinstall_os or check the host is not in installing
|
|
state, we should set check_in_installing to True.
|
|
Otherwise we will check the host is not in installing or installed.
|
|
We also make sure the user is admin or the owner of the host to avoid
|
|
unauthorized user to update host attributes.
|
|
"""
|
|
if check_in_installing:
|
|
if host.state.state == 'INSTALLING':
|
|
raise exception.Forbidden(
|
|
'host %s is not editable '
|
|
'when state is in installing' % host.name
|
|
)
|
|
elif not host.reinstall_os:
|
|
raise exception.Forbidden(
|
|
'host %s is not editable '
|
|
'when not to be reinstalled' % host.name
|
|
)
|
|
if user and not user.is_admin and host.creator_id != user.id:
|
|
raise exception.Forbidden(
|
|
'host %s is not editable '
|
|
'when user is not admin or the owner of the host' % host.name
|
|
)
|
|
|
|
|
|
def is_host_editable(
|
|
host, user=None,
|
|
check_in_installing=False
|
|
):
|
|
"""Get if host is editable."""
|
|
try:
|
|
check_host_editable(
|
|
host, user=user,
|
|
check_in_installing=check_in_installing
|
|
)
|
|
return True
|
|
except exception.Forbidden:
|
|
return False
|
|
|
|
|
|
def validate_host(host):
|
|
"""Validate host.
|
|
|
|
Makesure hostname is not empty, there is only one mgmt network,
|
|
The mgmt network is not in promiscuous mode.
|
|
"""
|
|
if not host.hostname:
|
|
raise exception.Invalidparameter(
|
|
'host %s does not set hostname' % host.name
|
|
)
|
|
if not host.host_networks:
|
|
raise exception.InvalidParameter(
|
|
'host %s does not have any network' % host.name
|
|
)
|
|
mgmt_interface_set = False
|
|
for host_network in host.host_networks:
|
|
if host_network.is_mgmt:
|
|
if mgmt_interface_set:
|
|
raise exception.InvalidParameter(
|
|
'host %s multi interfaces set mgmt ' % host.name
|
|
)
|
|
if host_network.is_promiscuous:
|
|
raise exception.InvalidParameter(
|
|
'host %s interface %s is mgmt but promiscuous' % (
|
|
host.name, host_network.interface
|
|
)
|
|
)
|
|
mgmt_interface_set = True
|
|
if not mgmt_interface_set:
|
|
raise exception.InvalidParameter(
|
|
'host %s has no mgmt interface' % host.name
|
|
)
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=UPDATED_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@utils.input_validates(name=utils.check_name)
|
|
@utils.wrap_to_dict(RESP_FIELDS)
|
|
def _update_host(host_id, session=None, user=None, **kwargs):
|
|
"""Update a host internal."""
|
|
host = _get_host(host_id, session=session)
|
|
if host.state.state == "SUCCESSFUL" and not host.reinstall_os:
|
|
logging.info("ignoring successful host: %s", host_id)
|
|
return {}
|
|
check_host_editable(
|
|
host, user=user,
|
|
check_in_installing=kwargs.get('reinstall_os', False)
|
|
)
|
|
return utils.update_db_object(session, host, **kwargs)
|
|
|
|
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_UPDATE_HOST
|
|
)
|
|
def update_host(host_id, user=None, session=None, **kwargs):
|
|
"""Update a host."""
|
|
return _update_host(host_id, session=session, user=user, **kwargs)
|
|
|
|
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_UPDATE_HOST
|
|
)
|
|
def update_hosts(data=[], user=None, session=None):
|
|
"""Update hosts."""
|
|
# TODO(xicheng): this batch function is not similar as others.
|
|
# try to make it similar output as others and batch update should
|
|
# tolerate partial failure.
|
|
hosts = []
|
|
for host_data in data:
|
|
hosts.append(_update_host(session=session, user=user, **host_data))
|
|
return hosts
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_DEL_HOST
|
|
)
|
|
@utils.wrap_to_dict(
|
|
RESP_FIELDS + ['status', 'host'],
|
|
host=RESP_FIELDS
|
|
)
|
|
def del_host(
|
|
host_id, force=False, from_database_only=False,
|
|
user=None, session=None, **kwargs
|
|
):
|
|
"""Delete a host.
|
|
|
|
If force, we delete the host anyway.
|
|
If from_database_only, we only delete the host record in databaes.
|
|
Otherwise we send to del host task to celery to delete the host
|
|
record in os installer and package installer, clean installation logs
|
|
and at last clean database record.
|
|
The backend will call this function again after it deletes the record
|
|
in os installer and package installer with from_database_only set.
|
|
"""
|
|
from compass.db.api import cluster as cluster_api
|
|
host = _get_host(host_id, session=session)
|
|
# force set host state to ERROR when we want to delete the
|
|
# host anyway even the host is in installing or already
|
|
# installed. It let the api know the deleting is in doing when backend
|
|
# is doing the real deleting. In future we may import a new state like
|
|
# INDELETE to indicate the deleting is processing.
|
|
# We need discuss about if we can delete a host when it is already
|
|
# installed by api.
|
|
if host.state.state != 'UNINITIALIZED' and force:
|
|
host.state.state = 'ERROR'
|
|
check_host_editable(
|
|
host, user=user,
|
|
check_in_installing=True
|
|
)
|
|
cluster_ids = []
|
|
for clusterhost in host.clusterhosts:
|
|
if clusterhost.state.state != 'UNINITIALIZED' and force:
|
|
clusterhost.state.state = 'ERROR'
|
|
# TODO(grace): here we check all clusters which use this host editable.
|
|
# Because in backend we do not have functions to delete host without
|
|
# reference its cluster. After deleting pure host supported in backend,
|
|
# we should change code here to is_cluster_editable.
|
|
# Here delete a host may fail even we set force flag.
|
|
cluster_api.check_cluster_editable(
|
|
clusterhost.cluster, user=user,
|
|
check_in_installing=True
|
|
)
|
|
cluster_ids.append(clusterhost.cluster_id)
|
|
|
|
# Delete host record directly if there is no need to delete it
|
|
# in backend or from_database_only is set.
|
|
if host.state.state == 'UNINITIALIZED' or from_database_only:
|
|
return utils.del_db_object(session, host)
|
|
else:
|
|
logging.info(
|
|
'send del host %s task to celery', host_id
|
|
)
|
|
from compass.tasks import client as celery_client
|
|
celery_client.celery.send_task(
|
|
'compass.tasks.delete_host',
|
|
(
|
|
user.email, host.id, cluster_ids
|
|
)
|
|
)
|
|
return {
|
|
'status': 'delete action sent',
|
|
'host': host,
|
|
}
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOST_CONFIG
|
|
)
|
|
@utils.wrap_to_dict(RESP_CONFIG_FIELDS)
|
|
def get_host_config(host_id, user=None, session=None, **kwargs):
|
|
"""Get host config."""
|
|
return _get_host(host_id, session=session)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOST_CONFIG
|
|
)
|
|
@utils.wrap_to_dict(RESP_DEPLOYED_CONFIG_FIELDS)
|
|
def get_host_deployed_config(host_id, user=None, session=None, **kwargs):
|
|
"""Get host deployed config."""
|
|
return _get_host(host_id, session=session)
|
|
|
|
|
|
# replace os_config to deployed_os_config in kwargs.
|
|
@utils.replace_filters(
|
|
os_config='deployed_os_config'
|
|
)
|
|
@utils.supported_filters(
|
|
UPDATED_DEPLOYED_CONFIG_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_ADD_HOST_CONFIG
|
|
)
|
|
@utils.wrap_to_dict(RESP_CONFIG_FIELDS)
|
|
def update_host_deployed_config(host_id, user=None, session=None, **kwargs):
|
|
"""Update host deployed config."""
|
|
host = _get_host(host_id, session=session)
|
|
check_host_editable(host, user=user)
|
|
check_host_validated(host)
|
|
return utils.update_db_object(session, host, **kwargs)
|
|
|
|
|
|
def _host_os_config_validates(
|
|
config, host, session=None, user=None, **kwargs
|
|
):
|
|
"""Check host os config's validation."""
|
|
metadata_api.validate_os_config(
|
|
config, host.os_id
|
|
)
|
|
|
|
|
|
@utils.input_validates_with_args(
|
|
put_os_config=_host_os_config_validates
|
|
)
|
|
@utils.output_validates_with_args(
|
|
os_config=_host_os_config_validates
|
|
)
|
|
@utils.wrap_to_dict(RESP_CONFIG_FIELDS)
|
|
def _update_host_config(host, session=None, user=None, **kwargs):
|
|
"""Update host config."""
|
|
check_host_editable(host, user=user)
|
|
return utils.update_db_object(session, host, **kwargs)
|
|
|
|
|
|
# replace os_config to put_os_config in kwargs.
|
|
# It tells db the os_config will be updated not patched.
|
|
@utils.replace_filters(
|
|
os_config='put_os_config'
|
|
)
|
|
@utils.supported_filters(
|
|
UPDATED_CONFIG_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_ADD_HOST_CONFIG
|
|
)
|
|
def update_host_config(host_id, user=None, session=None, **kwargs):
|
|
"""Update host config."""
|
|
host = _get_host(host_id, session=session)
|
|
return _update_host_config(
|
|
host, session=session, user=user, **kwargs
|
|
)
|
|
|
|
|
|
# replace os_config to patched_os_config in kwargs.
|
|
# It tells db os_config will be patched not be updated.
|
|
@utils.replace_filters(
|
|
os_config='patched_os_config'
|
|
)
|
|
@utils.supported_filters(
|
|
PATCHED_CONFIG_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_ADD_HOST_CONFIG
|
|
)
|
|
def patch_host_config(host_id, user=None, session=None, **kwargs):
|
|
"""Patch host config."""
|
|
host = _get_host(host_id, session=session)
|
|
return _update_host_config(
|
|
host, session=session, user=user, **kwargs
|
|
)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_DEL_HOST_CONFIG
|
|
)
|
|
@utils.wrap_to_dict(RESP_CONFIG_FIELDS)
|
|
def del_host_config(host_id, user=None, session=None):
|
|
"""delete a host config."""
|
|
host = _get_host(host_id, session=session)
|
|
check_host_editable(host, user=user)
|
|
return utils.update_db_object(
|
|
session, host, os_config={}, config_validated=False
|
|
)
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=SUPPORTED_NETOWORK_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOST_NETWORKS
|
|
)
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def list_host_networks(host_id, user=None, session=None, **filters):
|
|
"""Get host networks for a host."""
|
|
host = _get_host(host_id, session=session)
|
|
return utils.list_db_objects(
|
|
session, models.HostNetwork,
|
|
host_id=host.id, **filters
|
|
)
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=SUPPORTED_NETOWORK_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOST_NETWORKS
|
|
)
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def list_hostnetworks(user=None, session=None, **filters):
|
|
"""Get host networks."""
|
|
return utils.list_db_objects(
|
|
session, models.HostNetwork, **filters
|
|
)
|
|
|
|
|
|
def _get_hostnetwork(host_network_id, session=None, **kwargs):
|
|
"""Get hostnetwork by hostnetwork id."""
|
|
if isinstance(host_network_id, (int, long)):
|
|
return utils.get_db_object(
|
|
session, models.HostNetwork,
|
|
id=host_network_id, **kwargs
|
|
)
|
|
raise exception.InvalidParameter(
|
|
'host network id %s type is not int compatible' % host_network_id
|
|
)
|
|
|
|
|
|
def _get_host_network(host_id, host_network_id, session=None, **kwargs):
|
|
"""Get hostnetwork by host id and hostnetwork id."""
|
|
host = _get_host(host_id, session=session)
|
|
host_network = _get_hostnetwork(host_network_id, session=session, **kwargs)
|
|
if host_network.host_id != host.id:
|
|
raise exception.RecordNotExists(
|
|
'host %s does not own host network %s' % (
|
|
host.id, host_network.id
|
|
)
|
|
)
|
|
return host_network
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOST_NETWORKS
|
|
)
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def get_host_network(
|
|
host_id, host_network_id,
|
|
user=None, session=None, **kwargs
|
|
):
|
|
"""Get host network."""
|
|
return _get_host_network(
|
|
host_id, host_network_id, session=session
|
|
)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_LIST_HOST_NETWORKS
|
|
)
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def get_hostnetwork(host_network_id, user=None, session=None, **kwargs):
|
|
"""Get host network."""
|
|
return _get_hostnetwork(host_network_id, session=session)
|
|
|
|
|
|
@utils.supported_filters(
|
|
ADDED_NETWORK_FIELDS,
|
|
optional_support_keys=OPTIONAL_ADDED_NETWORK_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@utils.input_validates(
|
|
ip=utils.check_ip
|
|
)
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def _add_host_network(
|
|
host_id, exception_when_existing=True,
|
|
session=None, user=None, interface=None, ip=None, **kwargs
|
|
):
|
|
"""Add hostnetwork to a host."""
|
|
host = _get_host(host_id, session=session)
|
|
check_host_editable(host, user=user)
|
|
return utils.add_db_object(
|
|
session, models.HostNetwork,
|
|
exception_when_existing,
|
|
host.id, interface, ip=ip, **kwargs
|
|
)
|
|
|
|
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_ADD_HOST_NETWORK
|
|
)
|
|
def add_host_network(
|
|
host_id, exception_when_existing=True,
|
|
interface=None, user=None, session=None, **kwargs
|
|
):
|
|
"""Create a hostnetwork to a host."""
|
|
return _add_host_network(
|
|
host_id,
|
|
exception_when_existing,
|
|
interface=interface, session=session, user=user, **kwargs
|
|
)
|
|
|
|
|
|
def _get_hostnetwork_by_ip(
|
|
ip, session=None, **kwargs
|
|
):
|
|
ip_int = long(netaddr.IPAddress(ip))
|
|
return utils.get_db_object(
|
|
session, models.HostNetwork,
|
|
ip_int=ip_int, **kwargs
|
|
)
|
|
|
|
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_ADD_HOST_NETWORK
|
|
)
|
|
def add_host_networks(
|
|
exception_when_existing=False,
|
|
data=[], user=None, session=None
|
|
):
|
|
"""Create host networks."""
|
|
hosts = []
|
|
failed_hosts = []
|
|
for host_data in data:
|
|
host_id = host_data['host_id']
|
|
host = _get_host(host_id, session=session)
|
|
networks = host_data['networks']
|
|
host_networks = []
|
|
failed_host_networks = []
|
|
for network in networks:
|
|
host_network = _get_hostnetwork_by_ip(
|
|
network['ip'], session=session,
|
|
exception_when_missing=False
|
|
)
|
|
if (
|
|
host_network and not (
|
|
host_network.host_id == host.id and
|
|
host_network.interface == network['interface']
|
|
)
|
|
):
|
|
logging.error('ip %s exists in host network %s' % (
|
|
network['ip'], host_network.id
|
|
))
|
|
failed_host_networks.append(network)
|
|
else:
|
|
host_networks.append(_add_host_network(
|
|
host.id, exception_when_existing,
|
|
session=session, user=user, **network
|
|
))
|
|
if host_networks:
|
|
hosts.append({'host_id': host.id, 'networks': host_networks})
|
|
if failed_host_networks:
|
|
failed_hosts.append({
|
|
'host_id': host.id, 'networks': failed_host_networks
|
|
})
|
|
return {
|
|
'hosts': hosts,
|
|
'failed_hosts': failed_hosts
|
|
}
|
|
|
|
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def _update_host_network(
|
|
host_network, session=None, user=None, **kwargs
|
|
):
|
|
"""Update host network."""
|
|
check_host_editable(host_network.host, user=user)
|
|
return utils.update_db_object(session, host_network, **kwargs)
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=UPDATED_NETWORK_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@utils.input_validates(
|
|
ip=utils.check_ip
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_ADD_HOST_NETWORK
|
|
)
|
|
def update_host_network(
|
|
host_id, host_network_id, user=None, session=None, **kwargs
|
|
):
|
|
"""Update a host network by host id and host network id."""
|
|
host = _get_host(
|
|
host_id, session=session
|
|
)
|
|
if host.state.state == "SUCCESSFUL" and not host.reinstall_os:
|
|
logging.info("ignoring updating request for successful hosts")
|
|
return {}
|
|
|
|
host_network = _get_host_network(
|
|
host_id, host_network_id, session=session
|
|
)
|
|
return _update_host_network(
|
|
host_network, session=session, user=user, **kwargs
|
|
)
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=UPDATED_NETWORK_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@utils.input_validates(
|
|
ip=utils.check_ip
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_ADD_HOST_NETWORK
|
|
)
|
|
def update_hostnetwork(host_network_id, user=None, session=None, **kwargs):
|
|
"""Update a host network by host network id."""
|
|
host_network = _get_hostnetwork(
|
|
host_network_id, session=session
|
|
)
|
|
return _update_host_network(
|
|
host_network, session=session, user=user, **kwargs
|
|
)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_DEL_HOST_NETWORK
|
|
)
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def del_host_network(
|
|
host_id, host_network_id, user=None,
|
|
session=None, **kwargs
|
|
):
|
|
"""Delete a host network by host id and host network id."""
|
|
host_network = _get_host_network(
|
|
host_id, host_network_id, session=session
|
|
)
|
|
check_host_editable(host_network.host, user=user)
|
|
return utils.del_db_object(session, host_network)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_DEL_HOST_NETWORK
|
|
)
|
|
@utils.wrap_to_dict(RESP_NETWORK_FIELDS)
|
|
def del_hostnetwork(host_network_id, user=None, session=None, **kwargs):
|
|
"""Delete a host network by host network id."""
|
|
host_network = _get_hostnetwork(
|
|
host_network_id, session=session
|
|
)
|
|
check_host_editable(host_network.host, user=user)
|
|
return utils.del_db_object(session, host_network)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_GET_HOST_STATE
|
|
)
|
|
@utils.wrap_to_dict(RESP_STATE_FIELDS)
|
|
def get_host_state(host_id, user=None, session=None, **kwargs):
|
|
"""Get host state info."""
|
|
return _get_host(host_id, session=session).state
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=UPDATED_STATE_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_UPDATE_HOST_STATE
|
|
)
|
|
@utils.wrap_to_dict(RESP_STATE_FIELDS)
|
|
def update_host_state(host_id, user=None, session=None, **kwargs):
|
|
"""Update a host state."""
|
|
host = _get_host(host_id, session=session)
|
|
utils.update_db_object(session, host.state, **kwargs)
|
|
return host.state
|
|
|
|
|
|
@util.deprecated
|
|
@utils.supported_filters(
|
|
optional_support_keys=UPDATED_STATE_INTERNAL_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_UPDATE_HOST_STATE
|
|
)
|
|
@utils.wrap_to_dict(['status', 'host'])
|
|
def update_host_state_internal(
|
|
host_id, from_database_only=False,
|
|
user=None, session=None, **kwargs
|
|
):
|
|
"""Update a host state.
|
|
|
|
This function is called when host os is installed.
|
|
If from_database_only, the state is updated in database.
|
|
Otherwise a celery task sent to os installer and package installer
|
|
to do some future actions.
|
|
"""
|
|
# TODO(xicheng): should be merged into update_host_state
|
|
host = _get_host(host_id, session=session)
|
|
if 'ready' in kwargs and kwargs['ready'] and not host.state.ready:
|
|
ready_triggered = True
|
|
else:
|
|
ready_triggered = False
|
|
clusterhosts_ready = {}
|
|
clusters_os_ready = {}
|
|
if ready_triggered:
|
|
for clusterhost in host.clusterhosts:
|
|
cluster = clusterhost.cluster
|
|
if cluster.flavor_name:
|
|
clusterhosts_ready[cluster.id] = False
|
|
else:
|
|
clusterhosts_ready[cluster.id] = True
|
|
all_os_ready = True
|
|
for clusterhost_in_cluster in cluster.clusterhosts:
|
|
host_in_cluster = clusterhost_in_cluster.host
|
|
if host_in_cluster.id == host.id:
|
|
continue
|
|
if not host_in_cluster.state.ready:
|
|
all_os_ready = False
|
|
clusters_os_ready[cluster.id] = all_os_ready
|
|
logging.debug('host %s ready: %s', host_id, ready_triggered)
|
|
logging.debug("clusterhosts_ready is: %s", clusterhosts_ready)
|
|
logging.debug("clusters_os_ready is %s", clusters_os_ready)
|
|
|
|
if not ready_triggered or from_database_only:
|
|
logging.debug('%s state is set to %s', host.name, kwargs)
|
|
utils.update_db_object(session, host.state, **kwargs)
|
|
if not host.state.ready:
|
|
for clusterhost in host.clusterhosts:
|
|
utils.update_db_object(
|
|
session, clusterhost.state, ready=False
|
|
)
|
|
utils.update_db_object(
|
|
session, clusterhost.cluster.state, ready=False
|
|
)
|
|
status = '%s state is updated' % host.name
|
|
else:
|
|
from compass.tasks import client as celery_client
|
|
celery_client.celery.send_task(
|
|
'compass.tasks.os_installed',
|
|
(
|
|
host.id, clusterhosts_ready,
|
|
clusters_os_ready
|
|
)
|
|
)
|
|
status = '%s: clusterhosts ready %s clusters os ready %s' % (
|
|
host.name, clusterhosts_ready, clusters_os_ready
|
|
)
|
|
logging.info('action status: %s', status)
|
|
return {
|
|
'status': status,
|
|
'host': host.state
|
|
}
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@utils.wrap_to_dict(RESP_LOG_FIELDS)
|
|
def get_host_log_histories(host_id, user=None, session=None, **kwargs):
|
|
"""Get host log history."""
|
|
host = _get_host(host_id, session=session)
|
|
return utils.list_db_objects(
|
|
session, models.HostLogHistory, id=host.id, **kwargs
|
|
)
|
|
|
|
|
|
def _get_host_log_history(host_id, filename, session=None, **kwargs):
|
|
host = _get_host(host_id, session=session)
|
|
return utils.get_db_object(
|
|
session, models.HostLogHistory, id=host.id,
|
|
filename=filename, **kwargs
|
|
)
|
|
|
|
|
|
@utils.supported_filters([])
|
|
@database.run_in_session()
|
|
@utils.wrap_to_dict(RESP_LOG_FIELDS)
|
|
def get_host_log_history(host_id, filename, user=None, session=None, **kwargs):
|
|
"""Get host log history."""
|
|
return _get_host_log_history(
|
|
host_id, filename, session=session
|
|
)
|
|
|
|
|
|
@utils.supported_filters(
|
|
optional_support_keys=UPDATED_LOG_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@utils.wrap_to_dict(RESP_LOG_FIELDS)
|
|
def update_host_log_history(
|
|
host_id, filename, user=None,
|
|
session=None, **kwargs
|
|
):
|
|
"""Update a host log history."""
|
|
host_log_history = _get_host_log_history(
|
|
host_id, filename, session=session
|
|
)
|
|
return utils.update_db_object(session, host_log_history, **kwargs)
|
|
|
|
|
|
@utils.supported_filters(
|
|
ADDED_LOG_FIELDS,
|
|
optional_support_keys=UPDATED_LOG_FIELDS,
|
|
ignore_support_keys=IGNORE_FIELDS
|
|
)
|
|
@database.run_in_session()
|
|
@utils.wrap_to_dict(RESP_LOG_FIELDS)
|
|
def add_host_log_history(
|
|
host_id, exception_when_existing=False,
|
|
filename=None, user=None, session=None, **kwargs
|
|
):
|
|
"""add a host log history."""
|
|
host = _get_host(host_id, session=session)
|
|
return utils.add_db_object(
|
|
session, models.HostLogHistory, exception_when_existing,
|
|
host.id, filename, **kwargs
|
|
)
|
|
|
|
|
|
@utils.supported_filters(optional_support_keys=['poweron'])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_DEPLOY_HOST
|
|
)
|
|
@utils.wrap_to_dict(
|
|
RESP_DEPLOY_FIELDS,
|
|
host=RESP_CONFIG_FIELDS
|
|
)
|
|
def poweron_host(
|
|
host_id, poweron={}, user=None, session=None, **kwargs
|
|
):
|
|
"""power on host."""
|
|
from compass.tasks import client as celery_client
|
|
host = _get_host(host_id, session=session)
|
|
check_host_validated(host)
|
|
celery_client.celery.send_task(
|
|
'compass.tasks.poweron_host',
|
|
(host.id,)
|
|
)
|
|
return {
|
|
'status': 'poweron %s action sent' % host.name,
|
|
'host': host
|
|
}
|
|
|
|
|
|
@utils.supported_filters(optional_support_keys=['poweroff'])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_DEPLOY_HOST
|
|
)
|
|
@utils.wrap_to_dict(
|
|
RESP_DEPLOY_FIELDS,
|
|
host=RESP_CONFIG_FIELDS
|
|
)
|
|
def poweroff_host(
|
|
host_id, poweroff={}, user=None, session=None, **kwargs
|
|
):
|
|
"""power off host."""
|
|
from compass.tasks import client as celery_client
|
|
host = _get_host(host_id, session=session)
|
|
check_host_validated(host)
|
|
celery_client.celery.send_task(
|
|
'compass.tasks.poweroff_host',
|
|
(host.id,)
|
|
)
|
|
return {
|
|
'status': 'poweroff %s action sent' % host.name,
|
|
'host': host
|
|
}
|
|
|
|
|
|
@utils.supported_filters(optional_support_keys=['reset'])
|
|
@database.run_in_session()
|
|
@user_api.check_user_permission(
|
|
permission.PERMISSION_DEPLOY_HOST
|
|
)
|
|
@utils.wrap_to_dict(
|
|
RESP_DEPLOY_FIELDS,
|
|
host=RESP_CONFIG_FIELDS
|
|
)
|
|
def reset_host(
|
|
host_id, reset={}, user=None, session=None, **kwargs
|
|
):
|
|
"""reset host."""
|
|
from compass.tasks import client as celery_client
|
|
host = _get_host(host_id, session=session)
|
|
check_host_validated(host)
|
|
celery_client.celery.send_task(
|
|
'compass.tasks.reset_host',
|
|
(host.id,)
|
|
)
|
|
return {
|
|
'status': 'reset %s action sent' % host.name,
|
|
'host': host
|
|
}
|