python云资源管理_python管理云服务器

如今是云时代,公司买服务器也从传统的IDC托管到现在的各大云厂商采购 。这里,我们将以阿里云、腾讯云为例实现云服务器实例的获取。

1、首先部署django环境,然后安装django drf, 把drf注册到APPS中

INSTALLED_APPS =[

...'rest_framework',

]

2、在项目下新建一个Python Package命名为apps,settting.py配置路径, IDE把apps设置成Mark Directory as source root

importosimportsys#Build paths inside the project like this: os.path.join(BASE_DIR, ...)

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.insert(0, os.path.join(BASE_DIR,'apps'))

3、在apps可以创建app了, 创建python package命名为resources,然后把resources注册到APPS中

4、在resources下新建个models.py设计数据表,这一步,可以先获取阿里云和腾讯云的实例返回结果,然后再进行设计。然后把表同步到数据库

from django.db importmodelsclassCloud(models.Model):

name= models.CharField(max_length=50, verbose_name='云厂商名称', help_text='云厂商名称')

code= models.CharField(max_length=20, verbose_name='云厂商名称', help_text='云厂商名称')def __str__(self):returnself.nameclassServer(models.Model):

cloud= models.ForeignKey(Cloud, verbose_name='云厂商', help_text='云厂商')

instanceId= models.CharField(max_length=50, db_index=True, verbose_name='实例ID', help_text='实例ID')

instanceName= models.CharField(max_length=50, db_index=True, verbose_name='实例名', help_text='实例名')

instanceType= models.CharField(max_length=50, verbose_name='实例类型', help_text='实例类型')

osName= models.CharField(max_length=32, verbose_name='操作系统', help_text='操作系统')

cpu= models.CharField(max_length=32, verbose_name='cpu核数', help_text='cpu核数')

memory= models.CharField(max_length=32, verbose_name='内存G', help_text='内存G')

createdTime= models.DateTimeField(verbose_name='创建时间',help_text='创建时间', null=True, blank=True)

expiredTime= models.DateTimeField(verbose_name='到期时间', help_text='到期时间', null=True, blank=True)classIp(models.Model):

ip= models.GenericIPAddressField(verbose_name='IP地址', help_text='IP地址', null=True, blank=True)

inner= models.ForeignKey(Server, null=True, related_name='privateIpAddresses', verbose_name='内网IP', help_text='内网IP')

public= models.ForeignKey(Server, null=True, related_name='publicIpAddresses', verbose_name='外网IP', help_text='外网IP')

models.py

5、在 resources新建两个python package分别命名为aliyun(阿里云)、qcloud(腾讯云), 加下来就需要用到他们的Python SDK了

6、在settings.py中配置他们的secretId、secretKey、regions(区域)

#ALIYUN

ALIYUN_SECRETID = 'xxxxxxxxxxx'ALIYUN_SECRETKEY= 'xxxxxxxxxxxxxxxxx'ALIYUN_REGIONS= ["xxxx"]#QCLOUD

QCLOUD_SECRETID = 'xxxxxxxxxxx'QCLOUD_SECRETKEY= 'xxxxxxxxxxx'QCLOUD_REGIONS= ["xxxx"]

settings.py

阿里云

编辑aliyun.__init__.py

from django.conf importsettingsfrom aliyunsdkcore importclientdefgetClient():for region insettings.ALIYUN_REGIONS:try:returnclient.AcsClient(settings.ALIYUN_SECRETID, settings.ALIYUN_SECRETKEY, region)exceptException as err:print('获取阿里云client失败:', err)

aliyun.__init__.py

新建aliyun.ecs.py

importjsonfrom resources.aliyun importgetClientfrom aliyunsdkecs.request.v20140526.DescribeInstancesRequest importDescribeInstancesRequestfrom resources.serializers importServerSerializerdefgetInnerIps(VpcAttributes):return VpcAttributes['PrivateIpAddress']['IpAddress']defgetPlublicIps(EipAddress):

ip_list=[]

ip_list.append(EipAddress['IpAddress'])returnip_listdefsaveInstance(instance):#print(instance)

data ={}

data['cloud'] = 'aliyun'data['instanceId'] = instance['InstanceId']

data['instanceName'] = instance['InstanceName']

data['instanceType'] = instance['InstanceType']

data['osName'] = instance['OSName']

data['cpu'] = instance['Cpu']

data['memory'] = int(instance['Memory'] / 1024)

data['createdTime'] = instance['CreationTime']

data['expiredTime'] = instance['ExpiredTime']

data['innerIps'] = getInnerIps(instance['VpcAttributes'])

data['publicIps'] = getPlublicIps(instance['EipAddress'])

serializer= ServerSerializer(data=data)ifserializer.is_valid():

serializer.save()else:print('阿里云序列化错误:', serializer.errors)defgetEcsList():

client=getClient()

request=DescribeInstancesRequest()

request.set_accept_format('json')

request.set_InstanceNetworkType= 'vpc'request.set_PageSize(100)try:

resp=client.do_action(request)

data=json.loads(resp)

instances= data['Instances']['Instance']#saveInstance(instances[0])

print(len(instances))for instance ininstances:

saveInstance(instance)exceptException as err:print('获取阿里云实例失败:', err)

aliyun.ecs.py

腾讯云

编辑qcloud.__init__.py

from django.conf importsettingsfrom tencentcloud.common importcredentialfrom tencentcloud.common.exception.tencent_cloud_sdk_exception importTencentCloudSDKExceptiondefgetCredential():try:returncredential.Credential(settings.QCLOUD_SECRETID, settings.QCLOUD_SECRETKEY)exceptTencentCloudSDKException as err:print(err)

qcloud.__init__.py

创建qcloud.cvm.py

importjsonfrom django.conf importsettingsfrom tencentcloud.cvm.v20170312 importcvm_client, modelsfrom tencentcloud.common.exception.tencent_cloud_sdk_exception importTencentCloudSDKExceptionfrom resources.qcloud importgetCredentialfrom resources.serializers importServerSerializerdefgetCvmClient(region):

cred=getCredential()try:returncvm_client.CvmClient(cred, region)exceptTencentCloudSDKException as err:print('获取腾讯云client:错误:', err)defsaveInstance(instance):#print(instance)

data ={}

data['cloud'] = 'qcloud'data['instanceId'] = instance['InstanceId']

data['instanceName'] = instance['InstanceName']

data['instanceType'] = instance['InstanceType']

data['osName'] = instance['OsName']

data['cpu'] = instance['CPU']

data['memory'] = instance['Memory']

data['innerIps'] = instance['PrivateIpAddresses']

data['publicIps'] = instance['PublicIpAddresses']

data['createdTime'] = instance['CreatedTime']

data['expiredTime'] = instance['ExpiredTime']

serializer= ServerSerializer(data=data)ifserializer.is_valid():

serializer.save()else:print('腾讯云序列化错误:', serializer.errors)defgetCvmList():for region insettings.QCLOUD_REGIONS:try:

client=getCvmClient(region)

req=models.DescribeInstancesRequest()

resp=client.DescribeInstances(req)

data=json.loads(resp.to_json_string())

instances= data['InstanceSet']for instance ininstances:

saveInstance(instance)exceptException as err:print('获取腾讯云主机失败:', err)

qcloud.cvm.py

序列化和反序列化

创建resources.serializers.py

from rest_framework importserializersfrom . models importCloud, Server, IpclassServerSerializer(serializers.Serializer):

id=serializers.ReadOnlyField()

cloud= serializers.PrimaryKeyRelatedField(queryset=Cloud.objects.all(),help_text='云厂商', many=False)

instanceId= serializers.CharField(required=True, help_text='实例ID')

instanceName= serializers.CharField(required=True, help_text='实例名')

instanceType= serializers.CharField(required=True, help_text='实例类型')

osName= serializers.CharField(required=True, help_text='操作系统')

cpu= serializers.CharField(required=True, help_text='CPU核数')

memory= serializers.CharField(required=True, help_text='内存G数')

innerIps= serializers.ListField(help_text='内网IP', write_only=True)

publicIps= serializers.ListField(help_text='外网IP', write_only=True)

createdTime= serializers.DateTimeField(help_text='创建时间')

expiredTime= serializers.DateTimeField(help_text='到期时间')defgetCloudPk(self, code):try:

obj= Cloud.objects.get(code__exact=code)returnobj.idexceptCloud.DoesNotExist:print('云厂商不存在')raise serializers.ValidationError('云厂商不存在')defto_internal_value(self, data):

data['cloud'] = self.getCloudPk(data['cloud'])returnsuper(ServerSerializer, self).to_internal_value(data)defgetInstance(self, instanceId):try:return Server.objects.get(instanceId__exact=instanceId)exceptServer.DoesNotExist:returnNoneexceptException as err:raiseserializers.ValidationError(err.args)defcreate(self, validated_data):

instance= self.getInstance(validated_data['instanceId'])if instance is notNone:returnself.update(instance, validated_data)

innerIps= validated_data.pop('innerIps')

publicIps= validated_data.pop('publicIps')

instance= Server.objects.create(**validated_data)

self.check_inner_ip(innerIps, instance)

self.check_public_ip(publicIps, instance)returninstancedefcheck_inner_ip(self, innerIps, instance):

ip_queryset=instance.privateIpAddresses.all()

current_ip_obj=[]for ip ininnerIps:try:

ip_obj= Ip.objects.get(ip__exact=ip)exceptIp.DoesNotExist:

ip_obj= Ip.objects.create(ip=ip, inner=instance)

current_ip_obj.append(ip_obj)

not_exist_ip= set(ip_queryset) -set(current_ip_obj)for ip_obj innot_exist_ip:

ip_obj.delete()defcheck_public_ip(self, publicIps, instance):

ip_queryset=instance.publicIpAddresses.all()

current_ip_obj=[]for ip inpublicIps:try:

ip_obj= Ip.objects.get(ip__exact=ip)exceptIp.DoesNotExist:

ip_obj= Ip.objects.create(ip=ip, public=instance)

current_ip_obj.append(ip_obj)

not_exist_ip= set(ip_queryset) -set(current_ip_obj)for ip_obj innot_exist_ip:

ip_obj.delete()defupdate(self, instance, validated_data):

instance.instanceName= validated_data.get('instanceName')

instance.osName= validated_data.get('osName')

instance.cpu= validated_data.get('cpu')

instance.memory= validated_data.get('memory')

instance.createdTime= validated_data.get('createdTime')

instance.expiredTime= validated_data.get('expiredTime')

instance.save()

self.check_inner_ip(validated_data['innerIps'], instance)

self.check_public_ip(validated_data['publicIps'], instance)returninstancedefto_representation(self, instance):

ret=super(ServerSerializer, self).to_representation(instance)

ret['cloud'] ={'id': instance.cloud.id,'name': instance.cloud.name

}

ret['innerIps'] = [ip.ip for ip ininstance.privateIpAddresses.all()]

ret['publicIps'] = [ip.ip for ip ininstance.publicIpAddresses.all()]return ret

resources.serializers.py

新建resources.views.py

from django.http importHttpResponsefrom rest_framework importviewsetsfrom django.views importViewfrom resources.qcloud importcvmfrom resources.aliyun importecsfrom . serializers importServerSerializerfrom . models importServerclassQtest(View):def get(self, request, *args, **kwargs):

cvm.getCvmList()return HttpResponse('Qtest')classAtest(View):def get(self, request, *args, **kwargs):

ecs.getEcsList()return HttpResponse('Atest')classServerViewSet(viewsets.ModelViewSet):

queryset=Server.objects.all()

serializer_class= ServerSerializer

resources.views.py

新建resources.router.py

from rest_framework.routers importDefaultRouterfrom . views importServerViewSet

router=DefaultRouter()

router.register('servers', ServerViewSet, base_name='servers')

resources.router

新建resourcrs.urls.py

from django.conf.urls importurlfrom . views importQtest, Atest

urlpatterns=[

url(r'^qtest/', Qtest.as_view(), name='qtest'),

url(r'^atest/', Atest.as_view(), name='atest'),

]

resources.urls.py

编辑根urls.py

from django.conf.urls importurl, includefrom rest_framework.routers importDefaultRouterfrom resources.router importrouter as resources_router

router=DefaultRouter()

router.registry.extend(resources_router.registry)

urlpatterns=[

url(r'^test/', include('resources.urls')),

url(r'', include(router.urls)),

]

urls.py

采集数据

访问http://127.0.0.1:8000/test/atest 采集阿里云实例数据

访问http://127.0.0.1:8000/test/qtest采集腾讯云实例数据

任务调度

上面我们是通过http请求来进行数据采集,这只是一个用来测试的方法,在实际应用中,我们可以使用apscheduler任务调度模块进行定时任务。

安装django-apscheduler模块

pip install django-apscheduler

注册到APPS中

INSTALLED_APPS =[

...'django_apscheduler',

]

django-apscheduler模块会有两张表,django_apscheduler_djangojob (定义的任务),django_apscheduler_djangojobexecution(记录任务执行情况包括出现的异常)

所以我们需要同步下数据库

python manage.py makemigrations django_apscheduler

python manage.py migrate apscheduler

新建resources. apscheduler,py

from datetime importdatetimefrom apscheduler.schedulers.background importBackgroundSchedulerfrom django_apscheduler.jobstores importDjangoJobStore, register_job, register_events#建立一个后台执行的任务

scheduler =BackgroundScheduler()#任务添加存储

scheduler.add_jobstore(DjangoJobStore(), 'default')#任务调度,每3秒执行一次

@register_job(scheduler, "interval", seconds=3)defmyjob():print('my name is heboan--{}'.format(datetime.now()))#任务执行器

register_events(scheduler)

scheduler.start()

现在只需要在项目根urls.py导入resources. apscheduler即可

from resources import apscheduler

启动项目后,可以看到它每3秒就执行了一次,有兴趣也可以去数据库查看那两张表

我们也可以让任务在前台运行,这次我们把要执行的任务换成前面的云服务器数据采集。

先把之前根urls.py那个导入模块去掉

编辑resources. apscheduler,py

from datetime importdatetimefrom apscheduler.schedulers.background importBackgroundSchedulerfrom django_apscheduler.jobstores importDjangoJobStore, register_job, register_eventsfrom resources.qcloud.cvm importgetCvmListfrom resources.aliyun.ecs importgetEcsListfrom apscheduler.schedulers.blocking importBlockingScheduler#scheduler = BackgroundScheduler()#建立前台任务

scheduler =BlockingScheduler()

scheduler.add_jobstore(DjangoJobStore(),'default')

@register_job(scheduler,"interval", seconds=30)defsync_cloud():

getEcsList()#采集阿里云

getCvmList() #采集腾讯云

register_events(scheduler)

在resources下新建Python Package命名为management

在management下新建Python Package命名为commands

在 commands下新建文件schedule.py

现在我们执行下python manage.py,可以看到多出来一条可以执行的命令

现在,我们来编辑schedule.py

from django.core.management.base importBaseCommandfrom resources.apscheduler importschedulerclassCommand(BaseCommand):

help= "django schedule"

def handle(self, *args, **options):

scheduler.start()

最后我们就可以执行python manage.py schedule了

前台任务:只需要保持python manage.py schedule在运行就可以了,后台任务需要项目跑起来。看你喜欢怎么用了 ^_^

分页

当我们访问http://127.0.0.1:8000/servers/ 会把所有的实例都显示出来,比较好的做法是进行分页显示,最简单的方式就在settings.py种添加如下配置:

REST_FRAMEWORK ={'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination','PAGE_SIZE': 10 #每页显示的条数

}

这样整个全局就生效了,按每页显示10条进行分页

当然,我们也可以自定义分页,如下:

1、在项目(devops)下新建个文件paginations.py

from rest_framework.pagination importPageNumberPaginationclassPagination(PageNumberPagination):

page_size= 10 #每页显示的条数

page_size_query_param = 'page_size' #想要显示的页数

page_query_param = 'p' #指定页码的参数

max_page_size = 100 每页显示的最大条数

2、修改settings.py中的分页设置(这个也会导致全局生效)

REST_FRAMEWORK ={'DEFAULT_PAGINATION_CLASS': 'devops.paginations.Pagination', #这里配置成我们自定义的

'PAGE_SIZE': 10}

上面的配置完成后,就会全局使用我们自定义的分页配置,如果只只想要Servers使用自定义的分页配置,那么我们就不需要修改settings.py,只需要如下操作

...from devops.paginations importPaginationclassServerViewSet(viewsets.ModelViewSet):

queryset=Server.objects.all()

serializer_class=ServerSerializer

pagination_class= Pagination #指定自定义的分页类即可

搜索

服务器实例比较多,如果我们想要搜索出指定的服务器实例,比如根据instanceName来搜索(http://127.0.0.1:8000/servers/?instanceName=pr-es-01)

现在我们在浏览器访问http://127.0.0.1:8000/servers/?instanceName=pr-es-01, 会发现并没有做任何过滤!

那么我们该怎么办?

1、我们进行搜索其实就是对模型进行条件筛选

2、在drf中,就是对queryset进行操作了

classServerViewSet(viewsets.ModelViewSet):

queryset=Server.objects.all()

serializer_class=ServerSerializer

pagination_class=Paginationdefget_queryset(self):

queryset=super(ServerViewSet, self).get_queryset()#获取到instanceName参数

instanceName = self.request.query_params.get('instanceName')#如果有传递此参数则进行instanceName模糊查询

ifinstanceName:

queryset= queryset.filter(instanceName__icontains=instanceName)return queryset

但是一般我们不会使用上面的方法去实现搜索。我们会使用django-filter

当然首先必须要先安装

pip install django-filter

然后注册到APPS中

INSTALLED_APPS =[

...'django_filters',

]

然后可以在视图中使用了

...from django_filters.rest_framework importDjangoFilterBackendclassServerViewSet(viewsets.ModelViewSet):

queryset=Server.objects.all()

serializer_class=ServerSerializer

pagination_class=Pagination#使用过滤器

filter_backends =(DjangoFilterBackend,)

filter_fields= ("instanceName",)

为了支持模糊查询或其他更高级的查询,我们就需要自定义过滤器了

新建文件resources.filters.py

from django_filters.rest_framework importFilterSetimportdjango_filtersfrom resources.models importServerclassServerFilter(FilterSet):

instanceName= django_filters.CharFilter(lookup_expr="icontains") #支持模糊查询

classMeta:

model=Server

fields= ['instanceName']

然后在视图中指定过滤类就可以了

from resources.filters importServerFilterclassServerViewSet(viewsets.ModelViewSet):

queryset=Server.objects.all()

serializer_class=ServerSerializer

pagination_class=Pagination

filter_backends= (DjangoFilterBackend,) #可以放到全局配置中

filter_class = ServerFilter

上面我提到filter_backends = (DjangoFilterBackend,)可以放到全局配置中,这样视图中就不需要配置了。操作如下:

1、先把视图中这段配置去掉 : filter_backends = (DjangoFilterBackend,)

2、编辑settings.py

REST_FRAMEWORK ={'DEFAULT_PAGINATION_CLASS': 'devops.paginations.Pagination','PAGE_SIZE': 10,'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) #加上此配置即可

}

ffilter还可以进行一些高级的方法,比如可以查询多个字段匹配

importdjango_filtersfrom django.contrib.auth importget_user_modelfrom django.db.models importQ

User=get_user_model()classUserFilter(django_filters.rest_framework.FilterSet):"""用户过滤类"""username= django_filters.CharFilter(method='search_username')defsearch_username(self, queryset, name, value):return queryset.filter(Q(name__icontains=value)|Q(username__icontains=value))classMeta:

model=User

fields= ['username']

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值