Python之路【第二十二篇】CMDB项目

浅谈ITIL

TIL即IT基础架构库(Information Technology Infrastructure Library, ITIL,信息技术基础架构库)由英国政府部门CCTA(Central Computing and Telecommunications Agency)在20世纪80年代末制订,现由英国商务部OGC(Office of Government Commerce)负责管理,主要适用于IT服务管理(ITSM)。ITIL为企业的IT服务管理实践提供了一个客观、严谨、可量化的标准和规范html

ITIL 就是一个标准规范,他并非一个软件和系统,举例来讲若是想本身构建一个IT服务的系统能够按照这个规范去实现。有一个指定方针!前端

ITIL分为如下内容python

一、事件管理(Incident Management)数据库

事故管理负责记录、归类和安排专家处理事故并监督整个处理过程直至事故获得解决和终止。事故管理的目的是在尽量最小地影响客户和用户业务的状况下使IT系统恢复到服务级别协议所定义的服务级别。django

注释:故障申报处理模块,出现故障把事故给相应的人去处理!一步一步的解决!编程

二、问题管理(Problem Management)json

问题管理是指经过调查和分析IT基础架构的薄弱环节、查明事故产生的潜在缘由,并制定解决事故的方案和防止事故再次发生的措施,将因为问题和事故对业务产生的负面影响减少到最低的服务管理流程。与事故管理强调事故恢复的速度不一样,问题管理强调的是找出事故产生的根源,从而制定恰当的解决方案或防止其再次发生的预防措施。api

注释:相似知识库、提供一些帮助,定位问题和预防的措施。缓存

三、配置管理(Configuration Management)安全

配置管理是识别和确认系统的配置项,记录和报告配置项状态和变动请求,检验配置项的正确性和完整性等活动构成的过程,其目的是提供IT基础架构的逻辑模型,支持其它服务管理流程特别是变动管理和发布管理的运做。

注释:识别和确认系统的配置项,配置项能够是硬件、也能够是软件!

若是是硬件:一个主机、一个硬盘、一个鼠标均可以是配置项。

若是是软件:好比公司购买的软件

作的CMDB就是ITIL的“配置管理”,SaltStack最明显的做用就是批量管理,还有一个做用就是配置管理,他能够把你的机器配置成你想要的状态!你想要这个机器配置什么服务、什么软件!这也能够叫配置管理!

这个配置管理能够看作CMDB的中的一项功能

四、变动管理(Change Management)

变动管理是指为在最短的中断时间内完成基础架构或服务的任一方面的变动而对其进行控制的服务管理流程。变动管理的目标是确保在变动实施过程当中使用标准的方法和步骤,尽快地实施变动,以将由变动所致使的业务中断对业务的影响减少到最低。

注释:个人理解是举例来讲:在服务器须要替换的时候、修改主机名、这个都须要流程化、标准化。

五、发布管理(Release Management)

发布管理是指对通过测试后导入实际应用的新增或修改后的配置项进行分发和宣传的管理流程。发布管理之前又称为软件控制与分发

注释:代码发布,它能够作为一个独立的系统!

 

若是想在公司作自动化,按照这个5大块来作就不会偏离自动化偏离太远,ITIL真正实施的不多由于很大!不过咱们能够借鉴它来参考去作咱们自动化的东西!

上面5大块具体实现的目标:

'''
事件管理的目标是在不影响业务的状况下,尽量快速的恢复服务,从而保证最佳的效率和服务的可持续性。事件管理流程的创建包括事件分类,肯定事件的优先级和创建事件的升级机制。

问题管理是调查基础设施和全部可用信息,包括事件数据库,来肯定引发事件发生的真正潜在缘由,一块儿提供的服务中可能存在的故障。

配置管理的目标是:定义和控制服务与基础设施的部件,并保持准确的配置信息。

变动管理的目标是:以受控的方式,确保全部变动获得评估、批准、实施和评审。

发布管理的目标是:在实际运行环境的发布中,交付、分发并跟踪一个或多个变动。

服务台:服务台是IT部门和IT服务用户之间的单一联系点。它经过提供一个集中和专职的服务联系点促进了组织业务流程与服务管理基础架构集成。服务台的主要目标是协调客户(用户)和IT部门之间的联系,为IT服务运做提供支持,从而提升客户的满意度。
服务台:以上的流程是咱们运维和研发同窗在后台实现的,若是要后期要交给其余用户,就须要一个入口。完整的前端结合!
'''

CMDB介绍

CMDB --Configuration Management Database 配置管理数据库, CMDB存储与管理企业IT架构中设备的各类配置信息,它与全部服务支持和服务交付流程都紧密相联,支持这些流程的运转、发挥配置信息的价值,同时依赖于相关流程保证数据的准确性。

在实际的项目中,CMDB经常被认为是构建其它ITIL流程的基础而优先考虑,ITIL项目的成败与是否成功创建CMDB有很是大的关系。
70%~80%的IT相关问题与环境的变动有着直接的关系。实施变动管理的难点和重点并非工具,而是流程。即经过一个自动化的、可重复的流程管理变动,使得当变动发生的时候,有一个标准化的流程去执行,可以预测到这个变动对整个系统管理产生的影响,并对这些影响进行评估和控制。而变动管理流程自动化的实现关键就是CMDB。

为何70%~80%的IT现骨干问题与环境的变动有着直接的关系,举例来讲,若是在交大的公司中好比百度,好比两个部门的一个是百度地图一个是百度贴吧!由于若是系统比较庞大的话,没有一我的能完彻底全的了解整个系统的架构,若是在这种状况下,百度地图的同窗修改了一个借口,那么他不知道是否影响百度贴吧。万一百度贴吧有调用呢!因此在这种状况下就须要一个存储着整个系统架构和对应关系的系统,记录着它们之间的关系映射!

因此CMDB中至少包含以下的功能:整合、调和、同步、映射和可视化。

  • 整合是指可以充分利用来自其余数据源的信息,对CMDB中包含的记录源属性进行存取,将多个数据源合并至一个视图中,生成连同来自CMDB和其余数据源信息在内的报告;
  • 调和能力是指经过对来自每一个数据源的匹配字段进行对比,保证CMDB中的记录在多个数据源中没有重复现象,维持CMDB中每一个配置项目数据源的完整性;自动调整流程使得初始实施、数据库管理员的手动运做和现场维护支持工做降至最低;
  • 同步指确保CMDB中的信息可以反映联合数据源的更新状况,在联合数据源更新频率的基础上肯定CMDB更新日程,按照通过批准的变动来更新 CMDB,找出未被批准的变动;
  • 应用映射与可视化,说明应用间的关系并反应应用和其余组件之间的依存关系,了解变动形成的影响并帮助诊断问题。

而且在作自动化的前提是标准化,咱们在作CMDB的时候就至关于作标准化的过程,并能仅仅告诉研发和运维同窗怎么怎么作,若是没有一个系统强制要求他这样作那么以前的流程和标准对于运维和研发来讲他们已经习惯了,是很难实施的!

自动化的前提就是标准化和流程化!

CMDB自定义用户认证

本身建立一个表,作一个one-to-one去管理User表,至关于扩展它!就至关于有两张表.一个是Django自带的表一个是我扩展的表,因此在查询的时候比较麻烦!看下面代码

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
#必须导入User模块
class UserProfile(models.Model):
    '''
    用户表
    '''
    #使用Django提供的用户表,直接继承就能够了.在原生的User表里扩展!(原生的User表里就有用户名和密码)
    #必定要使用OneToOne,若是是正常的ForeignKey的话就表示User中的记录能够对应UserProfile中的多条记录!
    #而且OneToOne的实现不是在SQL级别实现的而是在代码基本实现的!
    user = models.OneToOneField(User)
    #名字
    name = models.CharField(max_length=32)
    #属组
    groups = models.ManyToManyField("UserGroup")
    #朋友
    friends = models.ManyToManyField('self',related_name='my_friends')
    status = models.ForeignKey("UserStatus",related_name='user_status',blank=True,null=True)

而且在调用的时候还须要去调用这个User表而不是直接调用UserProfile

{{ request.user.userprofile.name }}

那如今我要就写一张表有两种方式
1 彻底本身写
2 或者是说在Django的基础上先继承在扩展,上面的方式就直接是集成没有扩展
若是是简单的项目的话,就使用One-To-One的直接继承就好了.
若是是大项目的话建议使用第二种方式.既然是自定义的话里面不少都须要本身写

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class UserProfileManager(BaseUserManager):
    def create_user(self, email, name, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            name=name,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, name, password):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(email,
            password=password,
            name=name
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

class UserProfile(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    name = models.CharField(max_length=32)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = UserProfileManager()
    #USERNAME_FIELD 告诉Django那个为用户名字段
    USERNAME_FIELD = 'email'
    #指定必须字段,用户名默认就是必须字段了,咱们在指定一个必须字段
    REQUIRED_FIELDS = ['name']

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __str__(self):              # __unicode__ on Python 2
        return self.email

    #这个方法是用来控制admin的权限的
    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True
    #用来判断是否有权限查看其余app的默认返回True
    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True
    #静态方法,默认返回self.
    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

而且咱们建立的表,Django默认去Django的Model里去找,若是不想放进Model里面而是本身写的表的话
怎么办?Django默认仍是本身的认证表,咱们的明确的告诉Django不要用你本身的表了用个人表!
在哪里改呢?在setting里指定!

AUTH_USER_MODEL = 'assets.UserProfile'

而且在model里引入

from assets.user_models import UserProfile

如今在注册admin以后有个问题,就是当咱们注册了admin以后咱们在修改密码以后发现
在修改密码以后,密码是明文的了!以下图

这是什么缘由呢?就是由于你重写了那么Admin你也得从新配置下!

#!/usr/bin/env python
#-*- coding:utf-8 -*-


from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField

from assets.models import UserProfile


class UserCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
    fields, plus a repeated password."""
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = UserProfile
        fields = ('email', 'name')

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = UserProfile
        fields = ('email', 'password', 'name', 'is_active', 'is_admin')

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('email', 'name', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('name',)}),
        ('Permissions', {'fields': ('is_admin',)}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'date_of_birth', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()

# Now register the new UserAdmin...
#admin.site.register(UserProfile, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
#admin.site.unregister(Group)

而后在Djangoadmin中导入

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from django.contrib import admin
from assets import models
from assets.user_admin import UserAdmin
# Register your models here.
'''
下面的意思就是默认使用的是:
admin.site.register(models.UserProfile)
给他绑定上咱们自定义的admin
admin.site.register(models.UserProfile,UserAdmin)
'''
admin.site.register(models.UserProfile,UserAdmin)

就OK了,咱们在使用的时候就不要在去调用User表了,而直接使用我们定义的表就能够了。

而后顺便再看下Group是作什么用的,Django默认给咱们有一个Group组,若是不们不想用直接取消就能够了

from django.contrib.auth.models import Group
admin.site.unregister(Group)


#完整实例~~

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from django.contrib import admin
from assets import models
from assets.user_admin import UserAdmin
from django.contrib.auth.models import Group

# Register your models here.
'''
下面的意思就是默认使用的是:
admin.site.register(models.UserProfile)
给他绑定上咱们自定义的admin
admin.site.register(models.UserProfile,UserAdmin)
'''
admin.site.register(models.UserProfile,UserAdmin)
admin.site.unregister(Group)

效果以下:

这样就不适用Django组了在Admin中!

CMDB表结构设计

确认配置项,都要存什么设备:

服务器:
    -内存
    -CPU
    -Disk
    -网卡
    -raid
    -sn
    -型号
    -系统版本
    -状态

存储设备:
    -型号
    -Disk

网络设备:
    -网口数量
    -网卡信息(MAC地址等信息)
    -网卡速度
    -背板带宽
    -系统版本
    -管理IP

软件资产:
    -用途
    -版本

机房:
    -机房信息
    -机柜(最大U位,电源最大负载)
    -U位

设备有管理员
设备所属业务线:这里重要

业务线这里要写成有层级关系的业务线!
‘’‘
为何呢?举例来讲,百度贴吧的业务线,他下面有数据库的机器,有作缓存的、有作前端的。
一个业务线下面有好几个业务线!而且不能规定他有多少层!
这里很重要!相似多级评论~~~~~
’‘’

Restful API接口规范的设计与实现

理解RESTful架构 :http://www.ruanyifeng.com/blog/2011/09/restful 

RESTful API 设计指南 :http://www.ruanyifeng.com/blog/2014/05/restful_api.html 

了解Restful API设计规范后若是能使用起来是最好了,平时须要注意的是URL中不能有动词。

咱们总结一下什么是RESTful架构:

  1. 每个URI表明一种资源;
  2. 客户端和服务器之间,传递这种资源的某种表现层;
  3. 客户端经过四个HTTP动词,对服务器端资源进行操做,实现"表现层状态转化"。

最多见的一种设计错误,就是URI包含动词。由于"资源"表示一种实体,因此应该是名词,URI不该该有动词,动词应该放在HTTP协议中。
举例来讲,某个URI是/posts/show/1,其中show是动词,这个URI就设计错了,正确的写法应该是/posts/1,而后用GET方法表示show。
若是某些动做是HTTP动词表示不了的,你就应该把动做作成一种资源。好比网上汇款,从帐户1向帐户2汇款500元,错误的URI是:
  POST /accounts/1/transfer/500/to/2
正确的写法是把动词transfer改为名词transaction,资源不能是动词,可是能够是一种服务:
  POST /transaction HTTP/1.1
  Host: 127.0.0.1
  from=1&to=2&amount=500.00
另外一个设计误区,就是在URI中加入版本号:
  http://www.example.com/app/1.0/foo
  http://www.example.com/app/1.1/foo
  http://www.example.com/app/2.0/foo
由于不一样的版本,能够理解成同一种资源的不一样表现形式,因此应该采用同一个URI。版本号能够在HTTP请求头信息的Accept字段中进行区分(参见Versioning REST Services)http://www.informit.com/articles/article.aspx?p=1566460:

Django API框架

 重中之重:接口设计好

  • 可对内外灵活开放接口
  • 接口定义要标准化
  • 必定要提供排错依据 
  • 数据返回要标准
  • 要能增删改查
  • 全部异常要抓住为了排错
  • 接口安全要注意

接口定义要标准化 (不能说随便起个名字 返回的数据的格式标准化)

在别人调用你接口的时候的,要提示它由于什么缘由致使出错了,好比他提交的数据不合法/或者服务器问题,为何要作这个:防止给本身找麻烦,由于别人在调用你端口的时候刚开始很容易出错)

理解API:

APIApplication Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工做机制的细节。

简单理解API是咱们提供的一个URL当用户按照指定的格式提交到URL中,咱们在内部的views里执行操做,而后返回给用户状态or数据!

那么有没有现成的提供了以上“重中之重的API设计里提到的那些API设计原则呢”?

django-rest-framework    

django-rest-framework 是一款比较不错的API模块,他为咱们定义了不少功能和规范而且能够经过网页查看API

Some reasons you might want to use REST framework:

一、安装django-rest-framework

pip install djangorestframework

二、配置Django settings中注册APP

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'assets',
    'rest_framework',
]

三、在Project中总URL重引入APP中的URL

from django.conf.urls import url,include
from django.contrib import admin
from assets import rest_urls

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include(rest_urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

四、配置Serializers序列化数据,这里配置展现什么数据而且被rest_views调用

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from django.contrib.auth.models import Group
from rest_framework import serializers
from assets.models import UserProfile
from assets import models

#定义前端展现什么,吧许菊进行序列化
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = UserProfile
        fields = ('url', 'name', 'email')

五、和APP中的URL分开因此独立建立url&views

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from django.conf.urls import url, include
from rest_framework import routers
from assets import rest_views

router = routers.DefaultRouter()
#这里是url名称(看代码下面的图)
router.register(r'users', rest_views.UserViewSet)
router.register(r'groups', rest_views.GroupViewSet)
router.register(r'assets', rest_views.AssetViewSet)
router.register(r'servers', rest_views.ServerViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    #这里的route.urls这个把默认的路由分发改为类的形式了
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

views

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from django.contrib.auth.models import Group
from rest_framework import viewsets

from assets.serializers import UserSerializer, GroupSerializer,AssetSerializer,ServerSerializer
from assets.models import UserProfile
from assets import models

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    #这里是从获取数据命名必须为:queryset & serializer_class
    #可是这里获取全部数据的命令实际是否展现不是在这里设置的在serializers中设置
    queryset = UserProfile.objects.all()
    serializer_class = UserSerializer

六、测试

修改Serializers显示内容

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from django.contrib.auth.models import Group
from rest_framework import serializers
from assets.models import UserProfile
from assets import models

#定义前端展现什么,吧许菊进行序列化
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = UserProfile
        fields = ('url', 'name', 'email','password','is_admin')

打开URL

 

 

进入users表里

效果以下:

能够在Serializers中定义好须要展现什么API就能够帮你展现,而且会帮你写好提示以下!

而且支持json格式以下图:

注API适用场景

在什么状况适用API呢?

外部和内部须要快速访问数据的时候适用,若是是本身的APP或者Project下不能适用,虽然可使用可是至关于一个环了原本能够从本身内部快速取出来的(本身写的代码取)若是从APP取就慢不少了,至关于绕了一圈!

固然API也能够本身写不用他这个框架,可是提示的内容和标准本身在写API的时候须要注意!

API安全

那么问题来了API,上面写的API随便谁均可以调用API进行操做,确定这个是不安全的!那怎么办呢?

方案以下:

原理:

原理:
一、客户端与服务器都存放着用于验证的Token字段,值字段不管经过什么方法外部的黑客都是没法获取的。
二、客户端吧本地的用户名+时间戳+Token的组合进行MD5加密生成一段新的md5-token
三、客户端访问的时候携带:用户名、时间戳、生成的一段新的md5-token
四、服务端收到请求后,先判断用户名、时间戳是否合法(时间戳和当前时间不能大于2分钟)
五、用户名和时间戳都合法了,在去Redis中判断是否有当前用户的key判断是否在这2分钟有访问过,我这里设置Redis2分钟过时,即合法用户第一次访问后,把他的用户名加入到Redis中做为key:MD5做为vlaue存储。若是存在说明是在2分钟内访问的。拒绝
六、以上都经过以后说明是合法用户和合法请求,而后在判断MD5值是否相等若是相同认证经过,执行相关Veiws而后并返回相关的状态或数据

 

更多内容摘自Aelx老师的博客:http://www.cnblogs.com/alex3714/articles/5420433.html

相关文章
相关标签/搜索