-
Notifications
You must be signed in to change notification settings - Fork 396
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
754 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# -*- coding:utf-8 -*- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# -*- coding:utf-8 -*- | ||
|
||
from api.lib.cmdb.ci import CIManager | ||
from api.lib.cmdb.ci import CIRelationManager | ||
from api.lib.cmdb.const import ExistPolicy | ||
|
||
|
||
class DCIMBase(object): | ||
def __init__(self): | ||
self.type_id = None | ||
|
||
@staticmethod | ||
def add_relation(parent_id, child_id): | ||
if not parent_id or not child_id: | ||
return | ||
|
||
CIRelationManager().add(parent_id, child_id, valid=False, apply_async=False) | ||
|
||
def add(self, parent_id, **kwargs): | ||
ci_id = CIManager().add(self.type_id, exist_policy=ExistPolicy.REJECT, **kwargs) | ||
|
||
if parent_id: | ||
self.add_relation(parent_id, ci_id) | ||
|
||
return ci_id | ||
|
||
@classmethod | ||
def update(cls, _id, **kwargs): | ||
CIManager().update(_id, **kwargs) | ||
|
||
@classmethod | ||
def delete(cls, _id): | ||
CIManager().delete(_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# -*- coding:utf-8 -*- | ||
|
||
|
||
from api.lib.utils import BaseEnum | ||
|
||
|
||
class RackBuiltinAttributes(BaseEnum): | ||
U_COUNT = 'u_count' | ||
U_START = 'u_start' | ||
FREE_U_COUNT = 'free_u_count' | ||
U_SLOT_ABNORMAL = 'u_slot_abnormal' | ||
|
||
|
||
class OperateTypeEnum(BaseEnum): | ||
ADD_DEVICE = "0" | ||
REMOVE_DEVICE = "1" | ||
MOVE_DEVICE = "2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from flask_login import current_user | ||
|
||
from api.lib.cmdb.cache import AttributeCache | ||
from api.lib.cmdb.cache import CITypeCache | ||
from api.lib.cmdb.ci import CIManager | ||
from api.lib.mixin import DBMixin | ||
from api.models.cmdb import DCIMOperationHistory | ||
|
||
|
||
class OperateHistoryManager(DBMixin): | ||
cls = DCIMOperationHistory | ||
|
||
@classmethod | ||
def search(cls, page, page_size, fl=None, only_query=False, reverse=False, count_query=False, | ||
last_size=None, **kwargs): | ||
numfound, result = super(OperateHistoryManager, cls).search(page, page_size, fl, only_query, reverse, | ||
count_query, last_size, **kwargs) | ||
|
||
ci_ids = [i['ci_id'] for i in result] | ||
id2ci = {i['_id']: i for i in (CIManager.get_cis_by_ids(ci_ids) or []) if i} | ||
type2show_key = dict() | ||
for i in id2ci.values(): | ||
if i.get('_type') not in type2show_key: | ||
ci_type = CITypeCache.get(i.get('_type')) | ||
if ci_type: | ||
show_key = AttributeCache.get(ci_type.show_id or ci_type.unique_id) | ||
type2show_key[i['_type']] = show_key and show_key.name | ||
|
||
return numfound, result, id2ci, type2show_key | ||
|
||
def _can_add(self, **kwargs): | ||
kwargs['uid'] = current_user.uid | ||
|
||
return kwargs | ||
|
||
def _can_update(self, **kwargs): | ||
pass | ||
|
||
def _can_delete(self, **kwargs): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# -*- coding:utf-8 -*- | ||
|
||
|
||
from flask import abort | ||
|
||
from api.lib.cmdb.cache import CITypeCache | ||
from api.lib.cmdb.const import BuiltinModelEnum | ||
from api.lib.cmdb.dcim.base import DCIMBase | ||
from api.lib.cmdb.resp_format import ErrFormat | ||
|
||
|
||
class IDCManager(DCIMBase): | ||
def __init__(self): | ||
super(IDCManager, self).__init__() | ||
|
||
self.ci_type = CITypeCache.get(BuiltinModelEnum.DCIM_IDC) or abort( | ||
404, ErrFormat.dcim_builtin_model_not_found.format(BuiltinModelEnum.DCIM_IDC)) | ||
|
||
self.type_id = self.ci_type.id |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
# -*- coding:utf-8 -*- | ||
|
||
import itertools | ||
import redis_lock | ||
from flask import abort | ||
|
||
from api.extensions import rd | ||
from api.lib.cmdb.cache import CITypeCache | ||
from api.lib.cmdb.ci import CIManager | ||
from api.lib.cmdb.ci import CIRelationManager | ||
from api.lib.cmdb.const import BuiltinModelEnum | ||
from api.lib.cmdb.dcim.base import DCIMBase | ||
from api.lib.cmdb.dcim.const import OperateTypeEnum | ||
from api.lib.cmdb.dcim.const import RackBuiltinAttributes | ||
from api.lib.cmdb.dcim.history import OperateHistoryManager | ||
from api.lib.cmdb.resp_format import ErrFormat | ||
from api.lib.cmdb.search.ci.db.search import Search as SearchFromDB | ||
from api.lib.cmdb.search.ci_relation.search import Search as RelationSearch | ||
|
||
|
||
class RackManager(DCIMBase): | ||
def __init__(self): | ||
super(RackManager, self).__init__() | ||
|
||
self.ci_type = CITypeCache.get(BuiltinModelEnum.DCIM_RACK) or abort( | ||
404, ErrFormat.dcim_builtin_model_not_found.format(BuiltinModelEnum.DCIM_RACK)) | ||
|
||
self.type_id = self.ci_type.id | ||
|
||
@classmethod | ||
def update(cls, _id, **kwargs): | ||
if RackBuiltinAttributes.U_COUNT in kwargs: | ||
devices, _, _, _, _, _ = RelationSearch( | ||
[_id], | ||
level=[1], | ||
fl=[RackBuiltinAttributes.U_COUNT, RackBuiltinAttributes.U_START], | ||
count=1000000).search() | ||
for device in devices: | ||
u_start = device.get(RackBuiltinAttributes.U_START) | ||
u_count = device.get(RackBuiltinAttributes.U_COUNT) or 2 | ||
if u_start and u_start + u_count - 1 > kwargs[RackBuiltinAttributes.U_COUNT]: | ||
return abort(400, ErrFormat.dcim_rack_u_count_invalid) | ||
|
||
CIManager().update(_id, _sync=True, **kwargs) | ||
|
||
if RackBuiltinAttributes.U_COUNT in kwargs: | ||
payload = {RackBuiltinAttributes.FREE_U_COUNT: cls._calc_u_free_count(_id)} | ||
|
||
CIManager().update(_id, _sync=True, **payload) | ||
|
||
def delete(self, _id): | ||
super(RackManager, self).delete(_id) | ||
|
||
payload = {RackBuiltinAttributes.U_START: None} | ||
_, _, second_cis = CIRelationManager.get_second_cis(_id, per_page='all') | ||
for ci in second_cis: | ||
CIManager().update(ci['_id'], **payload) | ||
|
||
@staticmethod | ||
def _calc_u_free_count(rack_id, device_id=None, u_start=None, u_count=None): | ||
rack = CIManager.get_ci_by_id(rack_id, need_children=False) | ||
if not rack.get(RackBuiltinAttributes.U_COUNT): | ||
return 0 | ||
|
||
if device_id is not None and u_count is None: | ||
ci = CIManager().get_ci_by_id(device_id, need_children=False) | ||
u_count = ci.get(RackBuiltinAttributes.U_COUNT) or 2 | ||
|
||
if u_start and u_start + u_count - 1 > rack.get(RackBuiltinAttributes.U_COUNT): | ||
return abort(400, ErrFormat.dcim_rack_u_slot_invalid) | ||
|
||
devices, _, _, _, _, _ = RelationSearch( | ||
[rack_id], | ||
level=[1], | ||
fl=[RackBuiltinAttributes.U_COUNT, RackBuiltinAttributes.U_START], | ||
count=1000000).search() | ||
|
||
u_count_sum = 0 | ||
for device in devices: | ||
u_count_sum += (device.get(RackBuiltinAttributes.U_COUNT) or 2) | ||
if device_id is not None: | ||
_u_start = device.get(RackBuiltinAttributes.U_START) | ||
_u_count = device.get(RackBuiltinAttributes.U_COUNT) or 2 | ||
if not _u_start: | ||
continue | ||
|
||
if device.get('_id') != device_id and set(range(u_start, u_start + u_count)) & set( | ||
range(_u_start, _u_start + _u_count)): | ||
return abort(400, ErrFormat.dcim_rack_u_slot_invalid) | ||
|
||
return rack[RackBuiltinAttributes.U_COUNT] - u_count_sum | ||
|
||
def check_u_slot(self): | ||
racks, _, _, _, _, _ = SearchFromDB( | ||
"_type:{}".format(self.type_id), | ||
count=10000000, | ||
fl=[RackBuiltinAttributes.U_START, RackBuiltinAttributes.U_COUNT, RackBuiltinAttributes.U_SLOT_ABNORMAL], | ||
parent_node_perm_passed=True).search() | ||
|
||
for rack in racks: | ||
devices, _, _, _, _, _ = RelationSearch( | ||
[rack['_id']], | ||
level=[1], | ||
fl=[RackBuiltinAttributes.U_COUNT, RackBuiltinAttributes.U_START], | ||
count=1000000).search() | ||
|
||
u_slot_sets = [] | ||
for device in devices: | ||
u_start = device.get(RackBuiltinAttributes.U_START) | ||
u_count = device.get(RackBuiltinAttributes.U_COUNT) or 2 | ||
if u_start is not None and str(u_start).isdigit(): | ||
u_slot_sets.append(set(range(u_start, u_start + u_count))) | ||
|
||
if len(u_slot_sets) > 1: | ||
for a, b in itertools.combinations(u_slot_sets, 2): | ||
u_slot_abnormal = bool(a.intersection(b)) | ||
if u_slot_abnormal != rack.get(RackBuiltinAttributes.U_SLOT_ABNORMAL): | ||
payload = {RackBuiltinAttributes.U_SLOT_ABNORMAL: u_slot_abnormal} | ||
CIManager().update(rack['_id'], **payload) | ||
|
||
def add_device(self, rack_id, device_id, u_start, u_count=None): | ||
with (redis_lock.Lock(rd.r, "DCIM_RACK_OPERATE_{}".format(rack_id))): | ||
self._calc_u_free_count(rack_id, device_id, u_start, u_count) | ||
|
||
self.add_relation(rack_id, device_id) | ||
|
||
payload = {RackBuiltinAttributes.U_START: u_start} | ||
if u_count: | ||
payload[RackBuiltinAttributes.U_COUNT] = u_count | ||
CIManager().update(device_id, _sync=True, **payload) | ||
|
||
payload = { | ||
RackBuiltinAttributes.FREE_U_COUNT: self._calc_u_free_count(rack_id, device_id, u_start, u_count)} | ||
CIManager().update(rack_id, _sync=True, **payload) | ||
|
||
OperateHistoryManager().add(operate_type=OperateTypeEnum.ADD_DEVICE, rack_id=rack_id, ci_id=device_id) | ||
|
||
def remove_device(self, rack_id, device_id): | ||
with (redis_lock.Lock(rd.r, "DCIM_RACK_OPERATE_{}".format(rack_id))): | ||
CIRelationManager.delete_3(rack_id, device_id, apply_async=False, valid=False) | ||
|
||
payload = {RackBuiltinAttributes.FREE_U_COUNT: self._calc_u_free_count(rack_id)} | ||
CIManager().update(rack_id, _sync=True, **payload) | ||
|
||
payload = {RackBuiltinAttributes.U_START: None} | ||
CIManager().update(device_id, _sync=True, **payload) | ||
|
||
OperateHistoryManager().add(operate_type=OperateTypeEnum.REMOVE_DEVICE, rack_id=rack_id, ci_id=device_id) | ||
|
||
def move_device(self, rack_id, device_id, to_u_start): | ||
with (redis_lock.Lock(rd.r, "DCIM_RACK_OPERATE_{}".format(rack_id))): | ||
payload = {RackBuiltinAttributes.FREE_U_COUNT: self._calc_u_free_count(rack_id, device_id, to_u_start)} | ||
CIManager().update(rack_id, _sync=True, **payload) | ||
|
||
CIManager().update(device_id, _sync=True, **{RackBuiltinAttributes.U_START: to_u_start}) | ||
|
||
OperateHistoryManager().add(operate_type=OperateTypeEnum.MOVE_DEVICE, rack_id=rack_id, ci_id=device_id) | ||
|
||
def migrate_device(self, rack_id, device_id, to_rack_id, to_u_start): | ||
with (redis_lock.Lock(rd.r, "DCIM_RACK_OPERATE_{}".format(rack_id))): | ||
self._calc_u_free_count(to_rack_id, device_id, to_u_start) | ||
|
||
if rack_id != to_rack_id: | ||
CIRelationManager.delete_3(rack_id, device_id, apply_async=False, valid=False) | ||
|
||
self.add_relation(to_rack_id, device_id) | ||
|
||
payload = { | ||
RackBuiltinAttributes.FREE_U_COUNT: self._calc_u_free_count(to_rack_id, device_id, to_u_start)} | ||
CIManager().update(to_rack_id, _sync=True, **payload) | ||
|
||
CIManager().update(device_id, _sync=True, **{RackBuiltinAttributes.U_START: to_u_start}) | ||
|
||
if rack_id != to_rack_id: | ||
payload = {RackBuiltinAttributes.FREE_U_COUNT: self._calc_u_free_count(rack_id)} | ||
CIManager().update(rack_id, _sync=True, **payload) | ||
|
||
OperateHistoryManager().add(operate_type=OperateTypeEnum.REMOVE_DEVICE, rack_id=rack_id, ci_id=device_id) | ||
OperateHistoryManager().add(operate_type=OperateTypeEnum.ADD_DEVICE, rack_id=to_rack_id, ci_id=device_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# -*- coding:utf-8 -*- | ||
|
||
|
||
from flask import abort | ||
|
||
from api.lib.cmdb.cache import CITypeCache | ||
from api.lib.cmdb.ci import CIManager | ||
from api.lib.cmdb.const import BuiltinModelEnum | ||
from api.lib.cmdb.const import ExistPolicy | ||
from api.lib.cmdb.resp_format import ErrFormat | ||
|
||
|
||
class RegionManager(object): | ||
def __init__(self): | ||
self.ci_type = CITypeCache.get(BuiltinModelEnum.DCIM_REGION) or abort( | ||
404, ErrFormat.dcim_builtin_model_not_found.format(BuiltinModelEnum.DCIM_REGION)) | ||
|
||
self.type_id = self.ci_type.id | ||
|
||
def add(self, **kwargs): | ||
return CIManager().add(self.type_id, exist_policy=ExistPolicy.REJECT, **kwargs) | ||
|
||
@classmethod | ||
def update(cls, _id, **kwargs): | ||
CIManager().update(_id, **kwargs) | ||
|
||
@classmethod | ||
def delete(cls, _id): | ||
CIManager().delete(_id) |
Oops, something went wrong.