<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## **一、創建項目** 讓我們新建一個項目。 首先,通過Pycharm直接創建CMDB項目,安裝最新的Django3.2,生成一個app,名字就叫做assets,最后配置好settings中的語言和時區。這些基本過程以后就不再贅述了,不熟悉的請參考教程的前面部分。 創建成功后,初始狀態如下圖所示: ![](https://img.kancloud.cn/48/07/4807d286dcca3bfcc979d49428c2e5fe_1240x674.png) <br /> ## **二、模型設計** **說明:本項目采用SQLite數據庫** 模型設計是整個項目的重中之重,其它所有的內容其實都是圍繞它展開的。 而我們設計數據模型的原則和參考依據是前一節分析的項目需求和數據分類表。 我們的模型架構圖如下所示: ![](https://img.kancloud.cn/b7/e5/b7e57743dd95a4565d4ae2f815a22ad2_1240x746.png) <br /> ### **1.資產共有數據模型** 打開assets/models.py文件,首先我們要設計一張資產共有數據表: <details> <summary>assets/models.py</summary> ``` from django.db import models from django.contrib.auth.models import User # Create your models here. class Asset(models.Model): """ 所有資產的共有數據表 """ asset_type_choice = ( ('server', '服務器'), ('networkdevice', '網絡設備'), ('storagedevice', '存儲設備'), ('securitydevice', '安全設備'), ('software', '軟件資產'), ) asset_status = ( (0, '在線'), (1, '下線'), (2, '未知'), (3, '故障'), (4, '備用'), ) asset_type = models.CharField(choices=asset_type_choice, max_length=64, default='server', verbose_name="資產類型") name = models.CharField(max_length=64, unique=True, verbose_name="資產名稱") # 不可重復 sn = models.CharField(max_length=128, unique=True, verbose_name="資產序列號") # 不可重復 business_unit = models.ForeignKey('BusinessUnit', null=True, blank=True, verbose_name='所屬業務線', on_delete=models.SET_NULL) status = models.SmallIntegerField(choices=asset_status, default=0, verbose_name='設備狀態') manufacturer = models.ForeignKey('Manufacturer', null=True, blank=True, verbose_name='制造商', on_delete=models.SET_NULL) manage_ip = models.GenericIPAddressField(null=True, blank=True, verbose_name='管理IP') tags = models.ManyToManyField('Tag', blank=True, verbose_name='標簽') admin = models.ForeignKey(User, null=True, blank=True, verbose_name='資產管理員', related_name='admin', on_delete=models.SET_NULL) idc = models.ForeignKey('IDC', null=True, blank=True, verbose_name='所在機房', on_delete=models.SET_NULL) contract = models.ForeignKey('Contract', null=True, blank=True, verbose_name='合同', on_delete=models.SET_NULL) purchase_day = models.DateField(null=True, blank=True, verbose_name="購買日期") expire_day = models.DateField(null=True, blank=True, verbose_name="過保日期") price = models.FloatField(null=True, blank=True, verbose_name="價格") approved_by = models.ForeignKey(User, null=True, blank=True, verbose_name='批準人', related_name='approved_by', on_delete=models.SET_NULL) memo = models.TextField(null=True, blank=True, verbose_name='備注') c_time = models.DateTimeField(auto_now_add=True, verbose_name='批準日期') m_time = models.DateTimeField(auto_now=True, verbose_name='更新日期') def __str__(self): return '<%s> %s' % (self.get_asset_type_display(), self.name) class Meta: verbose_name = '資產總表' verbose_name_plural = "資產總表" ordering = ['-c_time'] ``` </details> <br /> 說明: * 導入django.contrib.auto.models內置的User表,作為我們CMDB項目的用戶表,用于保存管理員和批準人員的信息; * sn這個數據字段是所有資產都必須有,并且唯一不可重復的!通常來自自動收集的數據中; * name和sn一樣,也是唯一的; * asset\_type\_choice和asset\_status分別設計為兩個選擇類型 * adamin和approved\_by是分別是當前資產的管理員和將該資產上線的審批員,為了區分他們,設置了related\_name; * Asset表中的很多字段內容都無法自動獲取,需要我們手動輸入,比如合同、備注。 * 最關鍵的是其中的一些外鍵字段,設置為`on_delete=models.SET_NULL`,這樣的話,當關聯的對象被刪除的時候,不會影響到資產數據表。 <br /> ### **2.服務器模型** 服務器作為資產的一種,而且是最主要的管理對象,包含了一些重要的字段,其模型結構如下: ``` class Server(models.Model): """服務器設備""" sub_asset_type_choice = ( (0, 'PC服務器'), (1, '刀片機'), (2, '小型機'), ) created_by_choice = ( ('auto', '自動添加'), ('manual', '手工錄入'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) # 非常關鍵的一對一關聯!asset被刪除的時候一并刪除server sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="服務器類型") created_by = models.CharField(choices=created_by_choice, max_length=32, default='auto', verbose_name="添加方式") hosted_on = models.ForeignKey('self', related_name='hosted_on_server', blank=True, null=True, verbose_name="宿主機", on_delete=models.CASCADE) # 虛擬機專用字段 model = models.CharField(max_length=128, null=True, blank=True, verbose_name='服務器型號') raid_type = models.CharField(max_length=512, blank=True, null=True, verbose_name='Raid類型') os_type = models.CharField('操作系統類型', max_length=64, blank=True, null=True) os_distribution = models.CharField('發行商', max_length=64, blank=True, null=True) os_release = models.CharField('操作系統版本', max_length=64, blank=True, null=True) def __str__(self): return '%s--%s--%s <sn:%s>' % (self.asset.name, self.get_sub_asset_type_display(), self.model, self.asset.sn) class Meta: verbose_name = '服務器' verbose_name_plural = "服務器" ``` 說明: * 每臺服務器都唯一關聯著一個資產對象,因此使用OneToOneField構建了一個一對一字段,這非常重要! * 服務器又可分為幾種子類型,這里定義了三種; * 服務器添加的方式可以分為手動和自動; * 有些服務器是虛擬機或者docker生成的,沒有物理實體,存在于宿主機中,因此需要增加一個hosted\_on字段;這里認為,宿主機如果被刪除,虛擬機也就不存在了; * 服務器有型號信息,如果硬件信息中不包含,那么指的就是主板型號; * Raid類型在采用了Raid的時候才有,否則為空 * 操作系統相關信息包含類型、發行版本和具體版本。 <br /> ### **3.安全、網絡、存儲設備和軟件資產的模型** 這部分內容不是項目的主要內容,而且數據大多數不能自動收集和報告,很多都需要手工錄入。我這里給出了范例,更多的數據字段,可以自行添加。 ``` class SecurityDevice(models.Model): """安全設備""" sub_asset_type_choice = ( (0, '防火墻'), (1, '入侵檢測設備'), (2, '互聯網網關'), (4, '運維審計系統'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="安全設備類型") model = models.CharField(max_length=128, default='未知型號', verbose_name='安全設備型號') def __str__(self): return self.asset.name + "--" + self.get_sub_asset_type_display() + str(self.model) + " id:%s" % self.id class Meta: verbose_name = '安全設備' verbose_name_plural = "安全設備" class StorageDevice(models.Model): """存儲設備""" sub_asset_type_choice = ( (0, '磁盤陣列'), (1, '網絡存儲器'), (2, '磁帶庫'), (4, '磁帶機'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="存儲設備類型") model = models.CharField(max_length=128, default='未知型號', verbose_name='存儲設備型號') def __str__(self): return self.asset.name + "--" + self.get_sub_asset_type_display() + str(self.model) + " id:%s" % self.id class Meta: verbose_name = '存儲設備' verbose_name_plural = "存儲設備" class NetworkDevice(models.Model): """網絡設備""" sub_asset_type_choice = ( (0, '路由器'), (1, '交換機'), (2, '負載均衡'), (4, 'VPN設備'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="網絡設備類型") vlan_ip = models.GenericIPAddressField(blank=True, null=True, verbose_name="VLanIP") intranet_ip = models.GenericIPAddressField(blank=True, null=True, verbose_name="內網IP") model = models.CharField(max_length=128, default='未知型號', verbose_name="網絡設備型號") firmware = models.CharField(max_length=128, blank=True, null=True, verbose_name="設備固件版本") port_num = models.SmallIntegerField(null=True, blank=True, verbose_name="端口個數") device_detail = models.TextField(null=True, blank=True, verbose_name="詳細配置") def __str__(self): return '%s--%s--%s <sn:%s>' % (self.asset.name, self.get_sub_asset_type_display(), self.model, self.asset.sn) class Meta: verbose_name = '網絡設備' verbose_name_plural = "網絡設備" class Software(models.Model): """ 只保存付費購買的軟件 """ sub_asset_type_choice = ( (0, '操作系統'), (1, '辦公\開發軟件'), (2, '業務軟件'), ) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="軟件類型") license_num = models.IntegerField(default=1, verbose_name="授權數量") version = models.CharField(max_length=64, unique=True, help_text='例如: RedHat release 7 (Final)', verbose_name='軟件/系統版本') def __str__(self): return '%s--%s' % (self.get_sub_asset_type_display(), self.version) class Meta: verbose_name = '軟件/系統' verbose_name_plural = "軟件/系統" ``` 說明: * 每臺安全、網絡、存儲設備都通過一對一的方式唯一關聯這一個資產對象。 * 通過sub\_asset\_type又細分設備的子類型 * 對于軟件,它沒有物理形體,因此無須關聯一個資產對象; * 軟件只管理那些大型的收費軟件,關注點是授權數量和軟件版本。對于那些開源的或者免費的軟件,顯然不算公司的資產。 <br /> ### **4.機房、制造商、業務線、合同、資產標簽等數據模型** 這一部分是CMDB中相關的內容,數據表建立后,可以通過手動添加。 ~~~ class IDC(models.Model): """機房""" name = models.CharField(max_length=64, unique=True, verbose_name="機房名稱") memo = models.CharField(max_length=128, blank=True, null=True, verbose_name='備注') def __str__(self): return self.name class Meta: verbose_name = '機房' verbose_name_plural = "機房" class Manufacturer(models.Model): """廠商""" name = models.CharField('廠商名稱', max_length=64, unique=True) telephone = models.CharField('支持電話', max_length=30, blank=True, null=True) memo = models.CharField('備注', max_length=128, blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '廠商' verbose_name_plural = "廠商" class BusinessUnit(models.Model): """業務線""" parent_unit = models.ForeignKey('self', blank=True, null=True, related_name='parent_level', on_delete=models.SET_NULL) name = models.CharField('業務線', max_length=64, unique=True) memo = models.CharField('備注', max_length=64, blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '業務線' verbose_name_plural = "業務線" class Contract(models.Model): """合同""" sn = models.CharField('合同號', max_length=128, unique=True) name = models.CharField('合同名稱', max_length=64) memo = models.TextField('備注', blank=True, null=True) price = models.IntegerField('合同金額') detail = models.TextField('合同詳細', blank=True, null=True) start_day = models.DateField('開始日期', blank=True, null=True) end_day = models.DateField('失效日期', blank=True, null=True) license_num = models.IntegerField('license數量', blank=True, null=True) c_day = models.DateField('創建日期', auto_now_add=True) m_day = models.DateField('修改日期', auto_now=True) def __str__(self): return self.name class Meta: verbose_name = '合同' verbose_name_plural = "合同" class Tag(models.Model): """標簽""" name = models.CharField('標簽名', max_length=32, unique=True) c_day = models.DateField('創建日期', auto_now_add=True) def __str__(self): return self.name class Meta: verbose_name = '標簽' verbose_name_plural = "標簽" ~~~ 說明: * 機房可以有很多其它字段,比如城市、樓號、樓層和未知等等,如有需要可自行添加; * 業務線可以有子業務線,因此使用一個外鍵關聯自身模型; * 合同模型主要存儲財務部門關心的數據; * 資產標簽模型與資產是多對多的關系。 <br /> ### **5.CPU模型** 通常一臺服務器中只能有一種CPU型號,所以這里使用OneToOneField唯一關聯一個資產對象,而不是外鍵關系。服務器上可以有多個物理CPU,它們的型號都是一樣的。每個物理CPU又可能包含多核。 ~~~ class CPU(models.Model): """CPU組件""" asset = models.OneToOneField('Asset', on_delete=models.CASCADE) # 設備上的cpu肯定都是一樣的,所以不需要建立多個cpu數據,一條就可以,因此使用一對一。 cpu_model = models.CharField('CPU型號', max_length=128, blank=True, null=True) cpu_count = models.PositiveSmallIntegerField('物理CPU個數', default=1) cpu_core_count = models.PositiveSmallIntegerField('CPU核數', default=1) def __str__(self): return self.asset.name + ": " + self.cpu_model class Meta: verbose_name = 'CPU' verbose_name_plural = "CPU" ~~~ <br /> ### **6.RAM模型** 某個資產中可能有多條內存,所以這里必須是外鍵關系。其次,內存的sn號可能無法獲得,就必須通過內存所在的插槽未知來唯一確定每條內存。因此,`unique_together = ('asset', 'slot')`這條設置非常關鍵,相當于內存的主鍵了,每條內存數據必須包含slot字段,否則就不合法。 ~~~ class RAM(models.Model): """內存組件""" asset = models.ForeignKey('Asset', on_delete=models.CASCADE) sn = models.CharField('SN號', max_length=128, blank=True, null=True) model = models.CharField('內存型號', max_length=128, blank=True, null=True) manufacturer = models.CharField('內存制造商', max_length=128, blank=True, null=True) slot = models.CharField('插槽', max_length=64) capacity = models.IntegerField('內存大小(GB)', blank=True, null=True) def __str__(self): return '%s: %s: %s: %s' % (self.asset.name, self.model, self.slot, self.capacity) class Meta: verbose_name = '內存' verbose_name_plural = "內存" unique_together = ('asset', 'slot') # 同一資產下的內存,根據插槽的不同,必須唯一 ~~~ <br /> ### **7. 硬盤模型** 與內存相同的是,硬盤也可能有很多塊,所以也是外鍵關系。不同的是,硬盤通常都能獲取到sn號,使用sn作為唯一值比較合適,也就是`unique_together = ('asset', 'sn')`。硬盤有不同的接口,這里設置了4種以及unknown,可自行添加其它類別。 ~~~ class Disk(models.Model): """硬盤設備""" disk_interface_type_choice = ( ('SATA', 'SATA'), ('SAS', 'SAS'), ('SCSI', 'SCSI'), ('SSD', 'SSD'), ('unknown', 'unknown'), ) asset = models.ForeignKey('Asset', on_delete=models.CASCADE) sn = models.CharField('硬盤SN號', max_length=128) slot = models.CharField('所在插槽位', max_length=64, blank=True, null=True) model = models.CharField('磁盤型號', max_length=128, blank=True, null=True) manufacturer = models.CharField('磁盤制造商', max_length=128, blank=True, null=True) capacity = models.FloatField('磁盤容量(GB)', blank=True, null=True) interface_type = models.CharField('接口類型', max_length=16, choices=disk_interface_type_choice, default='unknown') def __str__(self): return '%s: %s: %s: %sGB' % (self.asset.name, self.model, self.slot, self.capacity) class Meta: verbose_name = '硬盤' verbose_name_plural = "硬盤" unique_together = ('asset', 'sn') ~~~ <br /> ### **8.網卡模型** 一臺設備中可能有很多塊網卡,所以網卡與資產也是外鍵的關系。另外,由于虛擬機的存在,網卡的mac地址可能會發生重復,無法唯一確定某塊網卡,因此通過網卡型號加mac地址的方式來唯一確定網卡。 ~~~ class NIC(models.Model): """網卡組件""" asset = models.ForeignKey('Asset', on_delete=models.CASCADE) # 注意要用外鍵 name = models.CharField('網卡名稱', max_length=64, blank=True, null=True) model = models.CharField('網卡型號', max_length=128) mac = models.CharField('MAC地址', max_length=64) # 虛擬機有可能會出現同樣的mac地址 ip_address = models.GenericIPAddressField('IP地址', blank=True, null=True) net_mask = models.CharField('掩碼', max_length=64, blank=True, null=True) bonding = models.CharField('綁定地址', max_length=64, blank=True, null=True) def __str__(self): return '%s: %s: %s' % (self.asset.name, self.model, self.mac) class Meta: verbose_name = '網卡' verbose_name_plural = "網卡" unique_together = ('asset', 'model', 'mac') # 資產、型號和mac必須聯合唯一。防止虛擬機中的特殊情況發生錯誤。 ~~~ <br /> ### **9. 其它模型** 比如機房、廠商、標簽、業務線、合同等其它信息。 ~~~ class IDC(models.Model): """機房""" name = models.CharField(max_length=64, unique=True, verbose_name="機房名稱") memo = models.CharField(max_length=128, blank=True, null=True, verbose_name='備注') def __str__(self): return self.name class Meta: verbose_name = '機房' verbose_name_plural = "機房" class Manufacturer(models.Model): """廠商""" name = models.CharField('廠商名稱', max_length=64, unique=True) telephone = models.CharField('支持電話', max_length=30, blank=True, null=True) memo = models.CharField('備注', max_length=128, blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '廠商' verbose_name_plural = "廠商" class BusinessUnit(models.Model): """業務線""" parent_unit = models.ForeignKey('self', blank=True, null=True, related_name='parent_level', on_delete=models.CASCADE) name = models.CharField('業務線名稱', max_length=64, unique=True) memo = models.CharField('備注', max_length=64, blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '業務線' verbose_name_plural = "業務線" class Contract(models.Model): """合同""" sn = models.CharField('合同號', max_length=128, unique=True) name = models.CharField('合同名稱', max_length=64) memo = models.TextField('備注', blank=True, null=True) price = models.IntegerField('合同金額') detail = models.TextField('合同詳細', blank=True, null=True) start_day = models.DateField('開始日期', blank=True, null=True) end_day = models.DateField('失效日期', blank=True, null=True) license_num = models.IntegerField('license數量', blank=True, null=True) c_day = models.DateField('創建日期', auto_now_add=True) m_day = models.DateField('修改日期', auto_now=True) def __str__(self): return self.name class Meta: verbose_name = '合同' verbose_name_plural = "合同" class Tag(models.Model): """標簽""" name = models.CharField('標簽名', max_length=32, unique=True) c_day = models.DateField('創建日期', auto_now_add=True) def __str__(self): return self.name class Meta: verbose_name = '標簽' verbose_name_plural = "標簽" ~~~ <br /> ### **10.日志模型** CMDB必須記錄各種日志,這是毫無疑問的!我們通常要記錄事件名稱、類型、關聯的資產、子事件、事件詳情、誰導致的、發生時間。這些都很重要! 尤其要注意的是,事件日志不能隨著關聯資產的刪除被一并刪除,也就是我們設置`on_delete=models.SET_NULL`的意義! ~~~ class EventLog(models.Model): """ 日志. 在關聯對象被刪除的時候,不能一并刪除,需保留日志。 因此,on_delete=models.SET_NULL """ name = models.CharField('事件名稱', max_length=128) event_type_choice = ( (0, '其它'), (1, '硬件變更'), (2, '新增配件'), (3, '設備下線'), (4, '設備上線'), (5, '定期維護'), (6, '業務上線\更新\變更'), ) asset = models.ForeignKey('Asset', blank=True, null=True, on_delete=models.SET_NULL) # 當資產審批成功時有這項數據 new_asset = models.ForeignKey('NewAssetApprovalZone', blank=True, null=True, on_delete=models.SET_NULL) # 當資產審批失敗時有這項數據 event_type = models.SmallIntegerField('事件類型', choices=event_type_choice, default=4) component = models.CharField('事件子項', max_length=256, blank=True, null=True) detail = models.TextField('事件詳情') date = models.DateTimeField('事件時間', auto_now_add=True) user = models.ForeignKey(User, blank=True, null=True, verbose_name='事件執行人', on_delete=models.SET_NULL) # 自動更新資產數據時沒有執行人 memo = models.TextField('備注', blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '事件紀錄' verbose_name_plural = "事件紀錄" ~~~ <br /> ### **11.新資產待審批區模型** 新資產的到來,并不能直接加入CMDB數據庫中,而是要通過管理員審批后,才可以上線的。這就需要一個新資產的待審批區。在該區中,以資產的sn號作為唯一值,確定不同的資產。除了關鍵的包含資產所有信息的data字段,為了方便審批員查看信息,我們還設計了一些廠商、型號、內存大小、CPU類型等字段。同時,有可能出現資產還未審批,更新數據就已經發過來的情況,所以需要一個數據更新日期字段。 ~~~ class NewAssetApprovalZone(models.Model): """新資產待審批區""" sn = models.CharField('資產SN號', max_length=128, unique=True) # 此字段必填 asset_type_choice = ( ('server', '服務器'), ('networkdevice', '網絡設備'), ('storagedevice', '存儲設備'), ('securitydevice', '安全設備'), ('software', '軟件資產'), ) asset_type = models.CharField(choices=asset_type_choice, default='server', max_length=64, blank=True, null=True, verbose_name='資產類型') manufacturer = models.CharField(max_length=64, blank=True, null=True, verbose_name='生產廠商') model = models.CharField(max_length=128, blank=True, null=True, verbose_name='型號') ram_size = models.PositiveIntegerField(blank=True, null=True, verbose_name='內存大小') cpu_model = models.CharField(max_length=128, blank=True, null=True, verbose_name='CPU型號') cpu_count = models.PositiveSmallIntegerField('CPU物理數量', blank=True, null=True) cpu_core_count = models.PositiveSmallIntegerField('CPU核心數量', blank=True, null=True) os_distribution = models.CharField('發行商', max_length=64, blank=True, null=True) os_type = models.CharField('系統類型', max_length=64, blank=True, null=True) os_release = models.CharField('操作系統版本號', max_length=64, blank=True, null=True) data = models.TextField('資產數據') # 此字段必填 c_time = models.DateTimeField('匯報日期', auto_now_add=True) m_time = models.DateTimeField('數據更新日期', auto_now=True) approved = models.BooleanField('是否批準', default=False) def __str__(self): return self.sn class Meta: verbose_name = '新上線待批準資產' verbose_name_plural = "新上線待批準資產" ordering = ['-c_time'] ~~~ <br /> ### **11.總結** 通過前面的內容,我們可以看出CMDB數據模型的設計非常復雜,我們這里還是省略了很多不太重要的部分,就這樣總共都有400多行代碼。其中每個模型需要保存什么字段、采用什么類型、什么關聯關系、定義哪些參數、數據是否可以為空,這些都是踩過各種坑后總結出來的,不是隨便就能定義的。所以,請務必詳細閱讀和揣摩這些模型的內容。 <br /> 一切沒有問題之后,注冊app,然后makemigrations以及migrate! 最后附上整個models.py文件的代碼: <br /> <details> <summary>models.py</summary> ``` from django.db import models from django.contrib.auth.models import User # Create your models here. class Asset(models.Model): """ 所有資產的共有數據表 """ asset_type_choice = ( ('server', '服務器'), ('networkdevice', '網絡設備'), ('storagedevice', '存儲設備'), ('securitydevice', '安全設備'), ('software', '軟件資產'), ) asset_status = ( (0, '在線'), (1, '下線'), (2, '未知'), (3, '故障'), (4, '備用'), ) asset_type = models.CharField(choices=asset_type_choice, max_length=64, default='server', verbose_name="資產類型") name = models.CharField(max_length=64, unique=True, verbose_name="資產名稱") # 不可重復 sn = models.CharField(max_length=128, unique=True, verbose_name="資產序列號") # 不可重復 business_unit = models.ForeignKey('BusinessUnit', null=True, blank=True, verbose_name='所屬業務線', on_delete=models.SET_NULL) status = models.SmallIntegerField(choices=asset_status, default=0, verbose_name='設備狀態') manufacturer = models.ForeignKey('Manufacturer', null=True, blank=True, verbose_name='制造商', on_delete=models.SET_NULL) manage_ip = models.GenericIPAddressField(null=True, blank=True, verbose_name='管理IP') tags = models.ManyToManyField('Tag', blank=True, verbose_name='標簽') admin = models.ForeignKey(User, null=True, blank=True, verbose_name='資產管理員', related_name='admin', on_delete=models.SET_NULL) idc = models.ForeignKey('IDC', null=True, blank=True, verbose_name='所在機房', on_delete=models.SET_NULL) contract = models.ForeignKey('Contract', null=True, blank=True, verbose_name='合同', on_delete=models.SET_NULL) purchase_day = models.DateField(null=True, blank=True, verbose_name="購買日期") expire_day = models.DateField(null=True, blank=True, verbose_name="過保日期") price = models.FloatField(null=True, blank=True, verbose_name="價格") approved_by = models.ForeignKey(User, null=True, blank=True, verbose_name='批準人', related_name='approved_by', on_delete=models.SET_NULL) memo = models.TextField(null=True, blank=True, verbose_name='備注') c_time = models.DateTimeField(auto_now_add=True, verbose_name='批準日期') m_time = models.DateTimeField(auto_now=True, verbose_name='更新日期') def __str__(self): return '<%s> %s' % (self.get_asset_type_display(), self.name) class Meta: verbose_name = '資產總表' verbose_name_plural = "資產總表" ordering = ['-c_time'] class Server(models.Model): """服務器設備""" sub_asset_type_choice = ( (0, 'PC服務器'), (1, '刀片機'), (2, '小型機'), ) created_by_choice = ( ('auto', '自動添加'), ('manual', '手工錄入'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) # 非常關鍵的一對一關聯!asset被刪除的時候一并刪除server sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="服務器類型") created_by = models.CharField(choices=created_by_choice, max_length=32, default='auto', verbose_name="添加方式") hosted_on = models.ForeignKey('self', related_name='hosted_on_server', blank=True, null=True, verbose_name="宿主機", on_delete=models.CASCADE) # 虛擬機專用字段 model = models.CharField(max_length=128, null=True, blank=True, verbose_name='服務器型號') raid_type = models.CharField(max_length=512, blank=True, null=True, verbose_name='Raid類型') os_type = models.CharField('操作系統類型', max_length=64, blank=True, null=True) os_distribution = models.CharField('發行商', max_length=64, blank=True, null=True) os_release = models.CharField('操作系統版本', max_length=64, blank=True, null=True) def __str__(self): return '%s--%s--%s <sn:%s>' % (self.asset.name, self.get_sub_asset_type_display(), self.model, self.asset.sn) class Meta: verbose_name = '服務器' verbose_name_plural = "服務器" class SecurityDevice(models.Model): """安全設備""" sub_asset_type_choice = ( (0, '防火墻'), (1, '入侵檢測設備'), (2, '互聯網網關'), (4, '運維審計系統'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="安全設備類型") model = models.CharField(max_length=128, default='未知型號', verbose_name='安全設備型號') def __str__(self): return self.asset.name + "--" + self.get_sub_asset_type_display() + str(self.model) + " id:%s" % self.id class Meta: verbose_name = '安全設備' verbose_name_plural = "安全設備" class StorageDevice(models.Model): """存儲設備""" sub_asset_type_choice = ( (0, '磁盤陣列'), (1, '網絡存儲器'), (2, '磁帶庫'), (4, '磁帶機'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="存儲設備類型") model = models.CharField(max_length=128, default='未知型號', verbose_name='存儲設備型號') def __str__(self): return self.asset.name + "--" + self.get_sub_asset_type_display() + str(self.model) + " id:%s" % self.id class Meta: verbose_name = '存儲設備' verbose_name_plural = "存儲設備" class NetworkDevice(models.Model): """網絡設備""" sub_asset_type_choice = ( (0, '路由器'), (1, '交換機'), (2, '負載均衡'), (4, 'VPN設備'), ) asset = models.OneToOneField('Asset', on_delete=models.CASCADE) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="網絡設備類型") vlan_ip = models.GenericIPAddressField(blank=True, null=True, verbose_name="VLanIP") intranet_ip = models.GenericIPAddressField(blank=True, null=True, verbose_name="內網IP") model = models.CharField(max_length=128, default='未知型號', verbose_name="網絡設備型號") firmware = models.CharField(max_length=128, blank=True, null=True, verbose_name="設備固件版本") port_num = models.SmallIntegerField(null=True, blank=True, verbose_name="端口個數") device_detail = models.TextField(null=True, blank=True, verbose_name="詳細配置") def __str__(self): return '%s--%s--%s <sn:%s>' % (self.asset.name, self.get_sub_asset_type_display(), self.model, self.asset.sn) class Meta: verbose_name = '網絡設備' verbose_name_plural = "網絡設備" class Software(models.Model): """ 只保存付費購買的軟件 """ sub_asset_type_choice = ( (0, '操作系統'), (1, '辦公\開發軟件'), (2, '業務軟件'), ) sub_asset_type = models.SmallIntegerField(choices=sub_asset_type_choice, default=0, verbose_name="軟件類型") license_num = models.IntegerField(default=1, verbose_name="授權數量") version = models.CharField(max_length=64, unique=True, help_text='例如: RedHat release 7 (Final)', verbose_name='軟件/系統版本') def __str__(self): return '%s--%s' % (self.get_sub_asset_type_display(), self.version) class Meta: verbose_name = '軟件/系統' verbose_name_plural = "軟件/系統" class CPU(models.Model): """CPU組件""" asset = models.OneToOneField('Asset', on_delete=models.CASCADE) # 設備上的cpu肯定都是一樣的,所以不需要建立多個cpu數據,一條就可以,因此使用一對一。 cpu_model = models.CharField('CPU型號', max_length=128, blank=True, null=True) cpu_count = models.PositiveSmallIntegerField('物理CPU個數', default=1) cpu_core_count = models.PositiveSmallIntegerField('CPU核數', default=1) def __str__(self): return self.asset.name + ": " + self.cpu_model class Meta: verbose_name = 'CPU' verbose_name_plural = "CPU" class RAM(models.Model): """內存組件""" asset = models.ForeignKey('Asset', on_delete=models.CASCADE) sn = models.CharField('SN號', max_length=128, blank=True, null=True) model = models.CharField('內存型號', max_length=128, blank=True, null=True) manufacturer = models.CharField('內存制造商', max_length=128, blank=True, null=True) slot = models.CharField('插槽', max_length=64) capacity = models.IntegerField('內存大小(GB)', blank=True, null=True) def __str__(self): return '%s: %s: %s: %s' % (self.asset.name, self.model, self.slot, self.capacity) class Meta: verbose_name = '內存' verbose_name_plural = "內存" unique_together = ('asset', 'slot') # 同一資產下的內存,根據插槽的不同,必須唯一 class Disk(models.Model): """硬盤設備""" disk_interface_type_choice = ( ('SATA', 'SATA'), ('SAS', 'SAS'), ('SCSI', 'SCSI'), ('SSD', 'SSD'), ('unknown', 'unknown'), ) asset = models.ForeignKey('Asset', on_delete=models.CASCADE) sn = models.CharField('硬盤SN號', max_length=128) slot = models.CharField('所在插槽位', max_length=64, blank=True, null=True) model = models.CharField('磁盤型號', max_length=128, blank=True, null=True) manufacturer = models.CharField('磁盤制造商', max_length=128, blank=True, null=True) capacity = models.FloatField('磁盤容量(GB)', blank=True, null=True) interface_type = models.CharField('接口類型', max_length=16, choices=disk_interface_type_choice, default='unknown') def __str__(self): return '%s: %s: %s: %sGB' % (self.asset.name, self.model, self.slot, self.capacity) class Meta: verbose_name = '硬盤' verbose_name_plural = "硬盤" unique_together = ('asset', 'sn') class NIC(models.Model): """網卡組件""" asset = models.ForeignKey('Asset', on_delete=models.CASCADE) # 注意要用外鍵 name = models.CharField('網卡名稱', max_length=64, blank=True, null=True) model = models.CharField('網卡型號', max_length=128) mac = models.CharField('MAC地址', max_length=64) # 虛擬機有可能會出現同樣的mac地址 ip_address = models.GenericIPAddressField('IP地址', blank=True, null=True) net_mask = models.CharField('掩碼', max_length=64, blank=True, null=True) bonding = models.CharField('綁定地址', max_length=64, blank=True, null=True) def __str__(self): return '%s: %s: %s' % (self.asset.name, self.model, self.mac) class Meta: verbose_name = '網卡' verbose_name_plural = "網卡" unique_together = ('asset', 'model', 'mac') # 資產、型號和mac必須聯合唯一。防止虛擬機中的特殊情況發生錯誤。 class IDC(models.Model): """機房""" name = models.CharField(max_length=64, unique=True, verbose_name="機房名稱") memo = models.CharField(max_length=128, blank=True, null=True, verbose_name='備注') def __str__(self): return self.name class Meta: verbose_name = '機房' verbose_name_plural = "機房" class Manufacturer(models.Model): """廠商""" name = models.CharField('廠商名稱', max_length=64, unique=True) telephone = models.CharField('支持電話', max_length=30, blank=True, null=True) memo = models.CharField('備注', max_length=128, blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '廠商' verbose_name_plural = "廠商" class BusinessUnit(models.Model): """業務線""" parent_unit = models.ForeignKey('self', blank=True, null=True, related_name='parent_level', on_delete=models.CASCADE) name = models.CharField('業務線名稱', max_length=64, unique=True) memo = models.CharField('備注', max_length=64, blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '業務線' verbose_name_plural = "業務線" class Contract(models.Model): """合同""" sn = models.CharField('合同號', max_length=128, unique=True) name = models.CharField('合同名稱', max_length=64) memo = models.TextField('備注', blank=True, null=True) price = models.IntegerField('合同金額') detail = models.TextField('合同詳細', blank=True, null=True) start_day = models.DateField('開始日期', blank=True, null=True) end_day = models.DateField('失效日期', blank=True, null=True) license_num = models.IntegerField('license數量', blank=True, null=True) c_day = models.DateField('創建日期', auto_now_add=True) m_day = models.DateField('修改日期', auto_now=True) def __str__(self): return self.name class Meta: verbose_name = '合同' verbose_name_plural = "合同" class Tag(models.Model): """標簽""" name = models.CharField('標簽名', max_length=32, unique=True) c_day = models.DateField('創建日期', auto_now_add=True) def __str__(self): return self.name class Meta: verbose_name = '標簽' verbose_name_plural = "標簽" class EventLog(models.Model): """ 日志. 在關聯對象被刪除的時候,不能一并刪除,需保留日志。 因此,on_delete=models.SET_NULL """ name = models.CharField('事件名稱', max_length=128) event_type_choice = ( (0, '其它'), (1, '硬件變更'), (2, '新增配件'), (3, '設備下線'), (4, '設備上線'), (5, '定期維護'), (6, '業務上線\更新\變更'), ) asset = models.ForeignKey('Asset', blank=True, null=True, on_delete=models.SET_NULL) # 當資產審批成功時有這項數據 new_asset = models.ForeignKey('NewAssetApprovalZone', blank=True, null=True, on_delete=models.SET_NULL) # 當資產審批失敗時有這項數據 event_type = models.SmallIntegerField('事件類型', choices=event_type_choice, default=4) component = models.CharField('事件子項', max_length=256, blank=True, null=True) detail = models.TextField('事件詳情') date = models.DateTimeField('事件時間', auto_now_add=True) user = models.ForeignKey(User, blank=True, null=True, verbose_name='事件執行人', on_delete=models.SET_NULL) # 自動更新資產數據時沒有執行人 memo = models.TextField('備注', blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name = '事件紀錄' verbose_name_plural = "事件紀錄" class NewAssetApprovalZone(models.Model): """新資產待審批區""" sn = models.CharField('資產SN號', max_length=128, unique=True) # 此字段必填 asset_type_choice = ( ('server', '服務器'), ('networkdevice', '網絡設備'), ('storagedevice', '存儲設備'), ('securitydevice', '安全設備'), ('software', '軟件資產'), ) asset_type = models.CharField(choices=asset_type_choice, default='server', max_length=64, blank=True, null=True, verbose_name='資產類型') manufacturer = models.CharField(max_length=64, blank=True, null=True, verbose_name='生產廠商') model = models.CharField(max_length=128, blank=True, null=True, verbose_name='型號') ram_size = models.PositiveIntegerField(blank=True, null=True, verbose_name='內存大小') cpu_model = models.CharField(max_length=128, blank=True, null=True, verbose_name='CPU型號') cpu_count = models.PositiveSmallIntegerField('CPU物理數量', blank=True, null=True) cpu_core_count = models.PositiveSmallIntegerField('CPU核心數量', blank=True, null=True) os_distribution = models.CharField('發行商', max_length=64, blank=True, null=True) os_type = models.CharField('系統類型', max_length=64, blank=True, null=True) os_release = models.CharField('操作系統版本號', max_length=64, blank=True, null=True) data = models.TextField('資產數據') # 此字段必填 c_time = models.DateTimeField('匯報日期', auto_now_add=True) m_time = models.DateTimeField('數據更新日期', auto_now=True) approved = models.BooleanField('是否批準', default=False) def __str__(self): return self.sn class Meta: verbose_name = '新上線待批準資產' verbose_name_plural = "新上線待批準資產" ordering = ['-c_time'] ``` </details>
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看