Skip to content

Commit

Permalink
xmt功能上传
Browse files Browse the repository at this point in the history
  • Loading branch information
YoLoveLife committed Jan 25, 2018
1 parent 043f5fd commit 70f848c
Show file tree
Hide file tree
Showing 30 changed files with 527 additions and 187 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ devEops正在不断成长
![TIMELINE](img/timeline.png)</br>

## <a name="howtoinstall"> 如何安装 </a>
devEops依赖于python2.7、诸多python第三方模块以及mysql数据库</br>
以下操作环境已经拥有python2.7以及mysql数据库
devEops依赖于python2.7、诸多python第三方模块、mysql数据库、redis缓存</br>
以下操作环境已经拥有python2.7、mysql数据库、redis缓存
```bash
$ cd path/to/project/folder/

Expand Down
7 changes: 7 additions & 0 deletions apps/authority/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ def get_full_name(self):
full_name = '%s' % (self.last_name,)# self.first_name)
return full_name.strip()

@property
def is_operationE(self):
for group in self.groups.all():
if group.id == 1:
return True
return False

def get_group_name(self):
"""
:return: Name of group
Expand Down
2 changes: 1 addition & 1 deletion apps/deveops/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def setUp(self):
def test_indexpage(self):
# response = self.c.get('/validate/login')
response = self.c.get('/')
self.assertEqual(response.status_code,301)
self.assertEqual(response.status_code,302)

def test_404page(self):
self.c.force_login(self.user)
Expand Down
65 changes: 44 additions & 21 deletions apps/manager/consumers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import redis,socket,json
from manager.interactive import YoShellSendThread,YoShellRecvThread
from manager.models import Host,Group
from django.conf import settings
from deveops.utils import aes

class YoSheelConsumer(WebsocketConsumer):
http_user = True
Expand All @@ -31,46 +33,67 @@ def catch_redis_instance(self):

class ManagerConsumer(YoSheelConsumer):

def before_connect(self,**kwargs):
host = Host.objects.filter(id=int(kwargs['pk'])).get()
groups = host.groups
self.jumper.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.target.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for group in groups.all():
for jumper in group.jumpers.all():
try:
print(aes.decrypt(jumper.sshpasswd))
print(aes.decrypt(host.sshpasswd))
self.jumper.connect(jumper.service_ip, username=jumper.normal_user,
key_filename=settings.RSA_KEY, port=jumper.sshport,password=aes.decrypt(jumper.sshpasswd))
jumpertransport = self.jumper.get_transport()
jumperchannel = jumpertransport.open_channel("direct-tcpip",
(host.service_ip,host.sshport),
(jumper.service_ip,jumper.sshport))

self.target.connect(host.service_ip, username=host.normal_user, key_filename=settings.RSA_KEY,
sock=jumperchannel, port=host.sshport,password=aes.decrypt(host.sshpasswd))
return 1
except socket.timeout:
continue
except Exception,ex:
continue

def connect(self, message, **kwargs):
#Catch Info
#DEMO
try:
self.jumper.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.jumper.connect('114.55.126.93', username='root', key_filename='/root/.ssh/id_rsa', port=52000)
jumpertransport = self.jumper.get_transport()
dest_addr = ('10.101.30.188', 22)
local_addr = ('114.55.126.93', 52000)
jumperchannel = jumpertransport.open_channel("direct-tcpip", dest_addr, local_addr)
self.target.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.target.connect('10.101.30.188', username='root', key_filename='/root/.ssh/id_rsa', sock=jumperchannel,port=22)
result = self.before_connect(**kwargs)
except socket.timeout:
self.message.reply_channel.send(
{"text": json.dumps(['stdout', '\033[1;3;31m连接服务器超时\033[0m'])}, immediately=True)
{"text": '\033[1;3;31m连接服务器超时\033[0m'},immediately=True)
self.message.reply_channel.send({"accept": False})
return
except Exception,ex:
self.message.reply_channel.send(
{"text": json.dumps(['stdout', '\033[1;3;31m连接服务器失败\033[0m'.format(ex=str(ex))])},
{"text": '\033[1;3;31m连接服务器失败\033[0m'},
immediately=True)
self.message.reply_channel.send({"accept": False})
return
if result == 1:
chan = self.target.invoke_shell(height=int(kwargs['rows']),width=int(kwargs['cols']))
# chan.send('export JAVA_HOME=/usr/local/java')
threadSend = YoShellSendThread(self.message,chan,self.catch_redis_instance())
threadSend.setDaemon = True
threadSend.start()

chan = self.target.invoke_shell(height=int(kwargs['rows']),width=int(kwargs['cols']))
# chan.send('export JAVA_HOME=/usr/local/java')
threadSend = YoShellSendThread(self.message,chan,self.catch_redis_instance())
threadSend.setDaemon = True
threadSend.start()

theadRecv = YoShellRecvThread(self.message.reply_channel.name,chan)
theadRecv.setDaemon = True
theadRecv.start()
self.message.reply_channel.send({"accept": True})
theadRecv = YoShellRecvThread(self.message.reply_channel.name,chan)
theadRecv.setDaemon = True
theadRecv.start()
self.message.reply_channel.send({"accept": True})
else:
self.message.reply_channel.send({"accept": False})

def receive(self, text=None, bytes=None, **kwargs):
#将用户的输入直接发送到redis的订阅者队列当中
if text is not None:
self.push_mission(self.message.reply_channel.name,text)

def disconnect(self, message, **kwargs):
print('kkkr')
# print('kkkr')
self.jumper.close()
self.target.close()
5 changes: 2 additions & 3 deletions apps/manager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ class Host(models.Model):
groups = models.ManyToManyField(Group,blank=True,related_name='hosts',verbose_name=_("Group"))#所属应用
storages = models.ManyToManyField(Storage,blank=True,related_name='hosts',verbose_name=_('Host'))
systemtype = models.ForeignKey(System_Type,on_delete=models.SET_NULL,null=True)

manage_ip = models.GenericIPAddressField(default='0.0.0.0')
manage_ip = models.GenericIPAddressField(default='0.0.0.0',null=True)
service_ip = models.GenericIPAddressField(default='0.0.0.0')
outer_ip = models.GenericIPAddressField(default='0.0.0.0')
outer_ip = models.GenericIPAddressField(default='0.0.0.0',null=True)
server_position = models.CharField(max_length=50,default='')#服务器位置
hostname = models.CharField(max_length=50,default='localhost.localdomain')#主机名称
normal_user = models.CharField(max_length=15, default='')#普通用户
Expand Down
6 changes: 3 additions & 3 deletions apps/manager/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from django.db.models import Q
def systemtypeQuery():
list=[]
choices=models.Host.SYSTEM_CHOICES
choices = models.System_Type.objects.all()
count=0
for choice in choices:
dit={}
dit['name']=choice[1]
dit['value']=models.Host.objects.filter(systemtype=choice[0]).count()
dit['name']=choice.name
dit['value']=models.Host.objects.filter(systemtype=choice).count()
list.append(dit)
return json.dumps(list, ensure_ascii=False, encoding='UTF-8')

Expand Down
25 changes: 6 additions & 19 deletions apps/manager/templates/manager/detail_host.html
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ <h3 class="box-title"><i class="fa fa-life-ring"></i>应用信息</h3>
</div>
</section>
<!-- 模态框(Modal) -->
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal fade" id="shell_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content" id="box">
<!--此部分为主体内容,将远程加载进来-->
Expand All @@ -314,6 +314,10 @@ <h3 class="box-title"><i class="fa fa-life-ring"></i>应用信息</h3>
window.history.go(-1);
}
$(document).ready(function () {
$('#shell_modal').on('hidden.bs.modal',function () {
$(this).removeData("bs.modal");
$(this).innerHTML="";
});
})
.on('click','#flush_host',function () {
$.ajax({
Expand All @@ -331,30 +335,13 @@ <h3 class="box-title"><i class="fa fa-life-ring"></i>应用信息</h3>
});
})
.on('click','#btn-passwd',function () {
$('#modal').modal({
$('#shell_modal').modal({
show: true,
backdrop: 'static',
keyboard: 'true',
remote:"{% url 'manager:hostshell' object.id %}"
});


{# if($('#show_passwd').html()==''){#}
{# $.ajax({#}
{# type:"GET",#}
{# url:"/api-manager/v1/host/{{ object.id }}/passwd/",#}
{# dataType:"json",#}
{# success:function(data){#}
{# var passwd = data[0].password;#}
{# $('#show_passwd').html(passwd);#}
{# },#}
{# error:function(data){#}
{# }#}
{# })#}
{# }#}
{# else{#}
{# $('#show_passwd').html('');#}
{# }#}
})
</script>
{% endblock %}
18 changes: 12 additions & 6 deletions apps/manager/templates/manager/manager_modal.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% load static %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
{# <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>#}
<h4 class="modal-title" id="myModalLabel">分配/回收资产</h4>
</div>

Expand All @@ -14,8 +14,9 @@ <h4 class="modal-title" id="myModalLabel">分配/回收资产</h4>
</div>

<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal" onclick="close_yoshell()">关闭</button>
</div>
<script src="{% static 'plugins/jQuery/jquery-3.2.1.min.js' %}"></script>
{#<script src="{% static 'plugins/jQuery/jquery-3.2.1.min.js' %}"></script>#}
<script src="{% static 'plugins/xterm/xterm.js' %}"></script>
<script src="{% static 'plugins/xterm/addons/attach/attach.js' %}"></script>
<script src="{% static 'plugins/xterm/addons/fit/fit.js' %}"></script>
Expand All @@ -34,14 +35,19 @@ <h4 class="modal-title" id="myModalLabel">分配/回收资产</h4>
ele.style.width = width;
ele.style.height = height;
tem.resize(size.cols, size.rows);
var socket = new WebSocket("ws://" + "192.168.122.224:9999/manager/{{ id }}/wds/"+tem.cols+"/"+tem.rows+"/");
socket = new WebSocket("ws://" + "192.168.122.224:9999/manager/{{ id }}/wds/"+tem.cols+"/"+tem.rows+"/");
tem.fit();
tem.focus();
socket.onopen= function () {
tem.attach(socket);
}
}
$(document).ready(function () {
make_yoshell(document.getElementById('yoshell'),{'cols':300,'rows':200});
})
function close_yoshell() {
socket.close();
tem.destroy();
}
make_yoshell(document.getElementById('yoshell'),{'cols':300,'rows':200});
{# $(document).ready(function () {#}
{##}
{# })#}
</script>
12 changes: 0 additions & 12 deletions apps/manager/templates/manager/new_update_host.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,6 @@ <h1>
<div class="row">
<div class="col-md-5">
{% csrf_token %}
<div class="box" style="display: none">
<div class="box-header">
<h3 class="box-title">主机信息修改提示</h3>
</div>
<div class="box-body">
<div class="row">
<div class="col-md-4">
<p class="alert alert-danger" id="modal-error"></p>
</div>
</div>
</div>
</div>
<div class="box">
<div class="box-header">
<h3 class="box-title">主机管理信息</h3>
Expand Down
8 changes: 5 additions & 3 deletions apps/manager/views/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from deveops.utils import aes
from timeline.decorator.manager import decorator_manager


class ManagerHostListView(LoginRequiredMixin,TemplateView):
template_name='manager/host.html'

Expand All @@ -22,6 +23,7 @@ def get_context_data(self, **kwargs):
def get(self,request,*args, **kwargs):
return super(ManagerHostListView, self).get(request, *args, **kwargs)


class ManagerHostCreateView(LoginRequiredMixin,HostPermission.HostAddRequiredMixin,CreateView):
model = models.Host
form_class = forms.HostCreateForm
Expand Down Expand Up @@ -52,9 +54,9 @@ def form_valid(self, form):

def get_form(self, form_class=None):
form = super(ManagerHostUpdateView,self).get_form(form_class)

sshpasswd = ''
form.initial['sshpasswd'] = aes.decrypt(sshpasswd)
#
# sshpasswd = ''
form.initial['sshpasswd'] = aes.decrypt(form.initial['sshpasswd'])
return form

def get_context_data(self, **kwargs):
Expand Down
17 changes: 13 additions & 4 deletions apps/templates/_left_sidebar.html
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,20 @@
<li><a href="{% url 'concert:music' %}" class="ajax-link"><i class="fa fa-music"></i>乐谱</a></li>
</ul>
</li>


<li class="treeview">
<a href="{% url 'xmt:create' %}" class="ajax-link">
<i class="fa fa-bookmark"></i>
<span>新媒体云服务平台(临时)</span>
</a>
<a href="#">
<i class="fa fa-lemon-o"></i>
<span>新媒体云服务平台(临时)</span>
<span>
<i class="fa fa-angle-double-down"></i>
</span>
</a>
<ul class="treeview-menu" style="display: none">
<li><a href="{% url 'xmt:statistics' %}" class="ajax-link"><i class="fa fa-dashboard"></i>发布统计</a></li>
<li><a href="{% url 'xmt:create' %}" class="ajax-link"><i class="fa fa-bookmark"></i>代码更新</a></li>
</ul>
</li>
{# <li class="treeview">#}
{# <a href="#">#}
Expand Down
16 changes: 15 additions & 1 deletion apps/utils/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,25 @@
from rest_framework.views import Response,status
from rest_framework.pagination import PageNumberPagination
from timeline.decorator.manager import decorator_manager
from permission import jumper as JumperPermission

class UtilsJumperListAPI(generics.ListAPIView):
module = models.Jumper
serializer_class = serializers.JumperSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
queryset = models.Jumper.objects.all()
return queryset
return queryset


class UtilsJumperRemoveAPI(generics.DestroyAPIView):
serializer_class = serializers.JumperSerializer
permission_classes = [JumperPermission.JumperDeleteRequiredMixin]

def delete(self, request, *args, **kwargs):
jumper = models.Jumper.objects.get(id=int(kwargs['pk']))
if jumper.groups.count() != 0:
return Response({'detail': '该跳板机下存在应用组无法删除'}, status=status.HTTP_406_NOT_ACCEPTABLE)
else:
jumper.delete()
return Response({'detail': '删除成功'}, status=status.HTTP_201_CREATED)
Loading

0 comments on commit 70f848c

Please sign in to comment.