├── vsphere
├── __init__.py
├── templatetags
│ ├── __init__.py
│ ├── multiply.py
│ ├── percent.py
│ └── divide.py
├── templates
│ ├── search.html
│ ├── resourcepool_list.html
│ ├── guests.html
│ ├── hypervisors.html
│ ├── resourcepools.html
│ ├── guest_list.html
│ ├── hypervisor_list.html
│ ├── home.html
│ ├── guest.html
│ ├── resourcepool.html
│ ├── head.html
│ ├── top10.html
│ ├── datacenter.html
│ ├── stats_by_resourcepool.html
│ ├── hypervisor.html
│ └── physical.html
├── urls.py
├── api.py
├── admin.py
├── models.py
└── views.py
├── MANIFEST.in
├── screenshots
├── 4_guest_details.png
├── 1_home_datacenter.png
├── 2_hypervisors_list.png
├── 5_statistics_top10.png
├── 6_statistics_pools.png
└── 3_hypervisor_details.png
├── tools
├── hypervisor.ini
└── import_hypervisor.py
├── setup.py
└── README.rst
/vsphere/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vsphere/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.rst
2 | recursive-include vsphere/templates *
3 | recursive-include vsphere/templatetags *
--------------------------------------------------------------------------------
/screenshots/4_guest_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julcollas/django-vsphere/HEAD/screenshots/4_guest_details.png
--------------------------------------------------------------------------------
/tools/hypervisor.ini:
--------------------------------------------------------------------------------
1 | [user1]
2 | user:user1
3 | password:password1
4 |
5 | [user2]
6 | user:user2
7 | password:password2
--------------------------------------------------------------------------------
/screenshots/1_home_datacenter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julcollas/django-vsphere/HEAD/screenshots/1_home_datacenter.png
--------------------------------------------------------------------------------
/screenshots/2_hypervisors_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julcollas/django-vsphere/HEAD/screenshots/2_hypervisors_list.png
--------------------------------------------------------------------------------
/screenshots/5_statistics_top10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julcollas/django-vsphere/HEAD/screenshots/5_statistics_top10.png
--------------------------------------------------------------------------------
/screenshots/6_statistics_pools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julcollas/django-vsphere/HEAD/screenshots/6_statistics_pools.png
--------------------------------------------------------------------------------
/screenshots/3_hypervisor_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julcollas/django-vsphere/HEAD/screenshots/3_hypervisor_details.png
--------------------------------------------------------------------------------
/vsphere/templatetags/multiply.py:
--------------------------------------------------------------------------------
1 | from django import template
2 |
3 | register = template.Library()
4 |
5 |
6 | @register.filter
7 | def multiply(value, arg):
8 | return value * arg
--------------------------------------------------------------------------------
/vsphere/templatetags/percent.py:
--------------------------------------------------------------------------------
1 | from django import template
2 |
3 | register = template.Library()
4 |
5 |
6 | @register.filter
7 | def percent(value, arg):
8 | return int(100 * value / arg)
--------------------------------------------------------------------------------
/vsphere/templatetags/divide.py:
--------------------------------------------------------------------------------
1 | from django import template
2 |
3 | register = template.Library()
4 |
5 |
6 | @register.filter
7 | def divide(value, arg):
8 | return "%.2f" % (value / float(arg))
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from setuptools import setup
3 | import os
4 |
5 | README = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
6 |
7 | # allow setup.py to be run from any path
8 | os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
9 |
10 | setup(
11 | name = 'django-vsphere',
12 | version = '0.7',
13 | packages = ['vsphere'],
14 | include_package_data = True,
15 | description = 'Django app for vSphere Dashboard.',
16 | long_description = README,
17 | author = 'Julien Collas',
18 | author_email = 'jul.collas@gmail.com',
19 | install_requires=['django-tastypie', 'python-mimeparse'],
20 | classifiers = [
21 | 'Environment :: Web Environment',
22 | 'Framework :: Django',
23 | 'Topic :: Software Development :: Libraries :: Python Modules',
24 | 'Programming Language :: Python',
25 | 'Topic :: Internet :: WWW/HTTP'
26 | ],
27 | )
28 |
--------------------------------------------------------------------------------
/vsphere/templates/search.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load multiply %}
3 | {% load percent %}
4 | {% block title %}
5 | vSphere - Search
6 | {% endblock %}
7 | {% block content %}
8 | {% if resourcepool_list %}
9 |
10 |
{{ resourcepool_list |length }} Resource Pools
11 | {% include "resourcepool_list.html" %}
12 |
13 | {% endif %}
14 |
15 | {% if hypervisor_list %}
16 |
17 |
{{ hypervisor_list |length }} Hypervisors
18 | {% include "hypervisor_list.html" %}
19 |
20 | {% endif %}
21 |
22 | {% if guest_list %}
23 |
24 |
{{ guest_list |length }} Guests
25 | {% include "guest_list.html" %}
26 |
27 | {% endif %}
28 | {% endblock %}
29 |
--------------------------------------------------------------------------------
/vsphere/urls.py:
--------------------------------------------------------------------------------
1 | from vsphere.api import GuestResource, HypervisorResource
2 | from django.conf.urls import patterns, include, url
3 | from tastypie.api import Api
4 |
5 | v1_api = Api(api_name='v1')
6 | v1_api.register(GuestResource())
7 | v1_api.register(HypervisorResource())
8 |
9 | urlpatterns = patterns(
10 | '',
11 | url(r'^$', 'vsphere.views.home'),
12 | url(r'^hypervisors$', 'vsphere.views.hypervisors'),
13 | url(r'^guests$', 'vsphere.views.guests'),
14 | url(r'^resourcepools$', 'vsphere.views.resourcepools'),
15 | url(r'^resourcepoolstats$', 'vsphere.views.stats_by_resourcepool'),
16 | url(r'^top10resourcepools$', 'vsphere.views.top10'),
17 | url(r'^physical$', 'vsphere.views.physical_statistics'),
18 | url(r'^datacenter$', 'vsphere.views.datacenter_statistics'),
19 | url(r'^hypervisor', 'vsphere.views.hypervisor_info'),
20 | url(r'^guest', 'vsphere.views.guest_info'),
21 | url(r'^resourcepool', 'vsphere.views.resourcepool'),
22 | url(r'^search', 'vsphere.views.search'),
23 | url(r'^api/', include(v1_api.urls)),
24 | )
25 |
--------------------------------------------------------------------------------
/vsphere/api.py:
--------------------------------------------------------------------------------
1 | from tastypie.resources import ModelResource
2 | from vsphere.models import Guest, Hypervisor
3 | from tastypie import fields
4 |
5 |
6 | class GuestResource(ModelResource):
7 | hypervisor = fields.CharField(attribute="hypervisor")
8 |
9 | class Meta:
10 | queryset = Guest.objects.all()
11 | include_resource_uri = False
12 | resource_name = 'guest'
13 | ordering = ['name']
14 | limit = 0
15 | filtering = {
16 | 'name': ('exact', 'startswith', 'icontains'),
17 | }
18 |
19 | def determine_format(self, request):
20 | return 'application/json'
21 |
22 |
23 | class HypervisorResource(ModelResource):
24 |
25 | class Meta:
26 | queryset = Hypervisor.objects.all()
27 | include_resource_uri = False
28 | resource_name = 'hypervisor'
29 | ordering = ['name']
30 | limit = 0
31 | filtering = {
32 | 'name': ('exact', 'startswith', 'icontains'),
33 | }
34 |
35 | def determine_format(self, request):
36 | return 'application/json'
37 |
--------------------------------------------------------------------------------
/vsphere/templates/resourcepool_list.html:
--------------------------------------------------------------------------------
1 | {% load multiply %}
2 | {% load percent %}
3 |
4 | {% block content %}
5 |
6 |
7 |
8 | Name
9 | Hosted Guest
10 | Average Memory
11 | Average Storage
12 | Average vCPU
13 |
14 |
15 |
16 | {% regroup resourcepool_list|dictsort:"name" by name as resourcepool_list_name %}
17 | {% for a in resourcepool_list_name %}
18 | {% for rp in a.list %}
19 |
20 | {{ rp.name }}
21 | {{ rp.guests | length }}
22 | {{ rp.memory_avg | multiply:1048576 | filesizeformat }}
23 | {{ rp.storage_avg | multiply:1048576 | filesizeformat }}
24 | {{ rp.vcpu_avg | floatformat }}
25 |
26 | {% endfor %}
27 | {% endfor %}
28 |
29 |
30 | {% endblock %}
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | django-vsphere is an app for `Django `_ to have a centralized dashboard for all your VMWare vSphere ESXi.
2 |
3 | Dependencies
4 | -----------
5 |
6 | - django-tastypie
7 | - python-mimeparse (un-resolved tastypie dependencie)
8 |
9 | Quick start
10 | -----------
11 |
12 | 1. Add "vsphere" to your INSTALLED_APPS setting like this::
13 |
14 | INSTALLED_APPS = (
15 | ...
16 | 'vsphere',
17 | )
18 |
19 | 2. Include the polls URLconf in your project urls.py like this::
20 |
21 | url(r'^', include('vsphere.urls')),
22 |
23 | 4. Run syncdb to create the vsphere models::
24 |
25 | python manage.py syncdb
26 |
27 | 5. Start the development server and visit http://127.0.0.1:8000/admin/ ::
28 |
29 | python manage.py runserver
30 |
31 | 6. Visit http://127.0.0.1:8000/ to display the dashboard.
32 |
33 | 7. Visit the guest API at http://127.0.0.1:8000/api/guest/?name=vm1
34 |
35 |
36 | Import
37 | -----------
38 |
39 | 1. You can find an example script to import an hypervisor in "tools".
40 |
41 | 2. run import
42 |
43 | $ pip install pysphere
44 |
45 | $ python import_hypervisor.py -H hv.example.com -u user1 -d DatacenterX -p mypassword
46 |
47 | 3. The import script can use password stored in ~/.hypervisor.ini
48 |
--------------------------------------------------------------------------------
/vsphere/templates/guests.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% block title %}
3 | vSphere - Guests
4 | {% endblock %}
5 | {% block content %}
6 |
7 |
{{ guest_list | length }} Guests
8 | {% include "guest_list.html" %}
9 |
10 | {% if guest_list.has_other_pages %}
11 |
34 | {% endif %}
35 | {% endblock %}
--------------------------------------------------------------------------------
/vsphere/templates/hypervisors.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load i18n %}
3 | {% block title %}
4 | vSphere - Hypervisors
5 | {% endblock %}
6 | {% block content %}
7 |
8 |
{{ hypervisor_list | length }} Hypervisors
9 | {% include "hypervisor_list.html" %}
10 |
11 |
12 | {% if hypervisor_list.has_other_pages %}
13 |
36 | {% endif %}
37 | {% endblock %}
--------------------------------------------------------------------------------
/vsphere/templates/resourcepools.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load i18n %}
3 | {% block title %}
4 | vSphere - Resource Pools
5 | {% endblock %}
6 | {% block content %}
7 |
8 |
{{ resourcepool_list | length }} Resource Pools
9 | {% include "resourcepool_list.html" %}
10 |
11 |
12 | {% if resourcepool_list.has_other_pages %}
13 |
36 | {% endif %}
37 | {% endblock %}
--------------------------------------------------------------------------------
/vsphere/templates/guest_list.html:
--------------------------------------------------------------------------------
1 | {% load multiply %}
2 | {% load percent %}
3 |
4 | {% block content %}
5 |
6 |
7 |
8 | Hostname
9 | Resource Pool
10 | Memory
11 | Disk
12 | vCPU
13 | Status
14 | Hypervisor
15 |
16 |
17 |
18 | {% for guest in guest_list %}
19 |
20 | {{ guest.name }}
21 | {{ guest.resourcePool }}
22 | {{ guest.memory | multiply:1048576 | filesizeformat }}
23 | {{ guest.get_disk_reserved | multiply:1048576 | filesizeformat }}
24 | {{ guest.vcpu }}
25 |
26 | {% if guest.poweredOn %}
27 |
28 |
29 |
30 | {% else %}
31 |
32 |
33 |
34 | {% endif %}
35 |
36 | {{ guest.get_hypervisor_name }}
37 |
38 | {% endfor %}
39 |
40 | {% endblock %}
--------------------------------------------------------------------------------
/vsphere/templates/hypervisor_list.html:
--------------------------------------------------------------------------------
1 | {% load multiply %}
2 | {% load percent %}
3 |
4 | {% block content %}
5 |
6 |
7 |
8 | Hostname
9 | Hosted Guest
10 | Reserved Memory
11 | Allocated Disk
12 | CPU Threads
13 | Allocated vCpu
14 | Datacenter
15 |
16 |
17 |
18 | {% for hv in hypervisor_list %}
19 |
20 | {{ hv.name }}
21 | {{ hv.get_number_guest }}
22 |
23 |
24 |
27 | {{ hv.memoryReserved|percent:hv.memorySize }}%
28 |
29 |
30 |
31 |
32 |
33 |
37 | {{ hv.diskReserved|percent:hv.get_datastores_size }}%
38 |
39 |
40 |
41 | {{ hv.numCpuThreads }}
42 | {{ hv.vcpuReserved }}
43 | {{ hv.datacenter }}
44 |
45 | {% endfor %}
46 |
47 |
48 | {% endblock %}
--------------------------------------------------------------------------------
/vsphere/templates/home.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load multiply %}
3 | {% load percent %}
4 | {% block title %}
5 | vSphere - Dashboard
6 | {% endblock %}
7 | {% block content %}
8 |
9 | {% for dc in datacenter|dictsort:"name" %}
10 |
11 |
12 |
{{ dc.name }}
13 |
14 |
15 | Hypervisors
16 | {{ dc.nb_hv }}
17 |
18 |
19 | Guests
20 | {{ dc.nb_guest }}
21 |
22 |
23 | CPU Consolidation
24 | {{ dc.cpu_consolidation|floatformat:3 }}
25 |
26 |
27 | Used Memory
28 |
29 |
30 |
33 | {{ dc.used_mem }} %
34 |
35 |
36 |
37 |
38 |
39 | Used Storage
40 |
41 |
42 |
45 | {{ dc.used_storage }} %
46 |
47 |
48 |
49 |
50 | {% if dc.raw_storage_reserved %}
51 |
52 | Raw Storage
53 | {{ dc.raw_storage_reserved | multiply:1048576 | filesizeformat }}
54 |
55 | {% endif %}
56 |
57 |
58 |
59 | {% endfor %}
60 |
61 | {% endblock %}
62 |
--------------------------------------------------------------------------------
/vsphere/admin.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.contrib import admin
3 | from vsphere.models import Datastore
4 | from vsphere.models import Hypervisor
5 | from vsphere.models import Disk
6 | from vsphere.models import Guest
7 | from vsphere.models import Network
8 | from vsphere.models import Interface
9 | from vsphere.models import VirtualNic
10 | from vsphere.models import Vswitch
11 |
12 |
13 | class DatastoreAdmin(admin.ModelAdmin):
14 | """
15 | DatastoreAdmin Class with display, filter and search settings
16 | """
17 | list_display = ['hypervisor', 'name', 'capacity']
18 | list_filter = ['hypervisor']
19 | search_fields = ['hypervisor']
20 | save_as = True
21 |
22 |
23 | class DiskAdmin(admin.ModelAdmin):
24 | """
25 | DiskAdmin Class with display, filter and search settings
26 | """
27 | list_display = ['guest', 'name', 'size', 'datastore']
28 | list_filter = ['guest']
29 | search_fields = ['guest']
30 | save_as = True
31 |
32 |
33 | class GuestAdmin(admin.ModelAdmin):
34 | """
35 | GuestAdmin Class with display, filter and search settings
36 | """
37 | list_display = ['name', 'hypervisor', 'vcpu', 'memory', 'resourcePool']
38 | list_filter = ['hypervisor', 'poweredOn', 'vcpu', 'memory', 'resourcePool']
39 | search_fields = ['name', 'hypervisor', 'resourcePool']
40 | save_as = True
41 |
42 |
43 | class HypervisorAdmin(admin.ModelAdmin):
44 | """
45 | HypervisorAdmin Class with display, filter and search settings
46 | """
47 | list_display = ['name', 'datacenter', 'vendor', 'memorySize']
48 | list_filter = ['datacenter', 'vendor', 'memorySize']
49 | search_fields = ['name']
50 | save_as = True
51 |
52 |
53 | class InterfaceAdmin(admin.ModelAdmin):
54 | """
55 | InterfaceAdmin Class with display, filter and search settings
56 | """
57 | list_display = ['hypervisor', 'name', 'vswitch']
58 | list_filter = ['hypervisor']
59 | search_fields = ['hypervisor']
60 | save_as = True
61 |
62 |
63 | class VirtualNicAdmin(admin.ModelAdmin):
64 | """
65 | VirtualNicAdmin Class with display, filter and search settings
66 | """
67 | list_display = ['guest', 'name', 'mac', 'network']
68 | list_filter = ['guest']
69 | search_fields = ['guest', 'name', 'network']
70 | save_as = True
71 |
72 |
73 | class VswitchAdmin(admin.ModelAdmin):
74 | """
75 | VirtualNicAdmin Class with display, filter and search settings
76 | """
77 | list_display = ['hypervisor', 'name']
78 | save_as = True
79 |
80 |
81 | class NetworkAdmin(admin.ModelAdmin):
82 | """
83 | VirtualNicAdmin Class with display, filter and search settings
84 | """
85 | list_display = ['name', 'vlanId']
86 | save_as = True
87 |
88 |
89 | admin.site.register(Datastore, DatastoreAdmin)
90 | admin.site.register(Hypervisor, HypervisorAdmin)
91 | admin.site.register(Disk, DiskAdmin)
92 | admin.site.register(Guest, GuestAdmin)
93 | admin.site.register(Interface, InterfaceAdmin)
94 | admin.site.register(VirtualNic, VirtualNicAdmin)
95 | admin.site.register(Vswitch, VswitchAdmin)
96 | admin.site.register(Network, NetworkAdmin)
97 |
--------------------------------------------------------------------------------
/vsphere/templates/guest.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load multiply %}
3 | {% load percent %}
4 | {% block title %}
5 | vSphere - {{ guest.name }}
6 | {% endblock %}
7 | {% block content %}
8 | {{ guest.name }}
9 |
10 |
11 |
12 |
General
13 |
14 |
15 |
Guest OS
16 |
{{ guest.osVersion }}
17 |
18 |
19 |
vCpu
20 |
{{ guest.vcpu }}
21 |
22 |
23 |
Memory
24 |
{{ guest.memory | multiply:1048576 | filesizeformat }}
25 |
26 |
27 |
Status
28 |
29 | {% if guest.poweredOn %}
30 |
31 |
32 |
33 | {% else %}
34 |
35 |
36 |
37 | {% endif %}
38 |
39 |
40 |
41 |
Resource Pool
42 |
{{ guest.resourcePool }}
43 |
44 |
45 |
Datacenter
46 |
{{ guest.hypervisor.datacenter }}
47 |
48 |
52 |
53 |
Notes
54 |
{{ guest.annotation }}
55 |
56 |
57 |
Interfaces
58 |
{{ vnics | length }}
59 |
60 |
61 |
62 |
63 |
64 |
65 |
Storage - {{ disks | length }} Disk(s)
66 |
67 | {% for disk in disks %}
68 |
69 |
70 | {{ disk.name }}
71 |
72 |
{{ disk.thin|yesno:"Thin-provisioning, Thick-provisioning" }}
73 |
{{ disk.size | multiply:1048576 | filesizeformat }}
74 |
82 |
83 | {% endfor %}
84 |
85 |
86 |
87 |
Network - {{ vnics | length }} Network(s)
88 |
89 | {% for vnic in vnics %}
90 |
91 |
92 |
93 | Network
94 | {{ vnic.network.name }}
95 |
96 |
97 | Interface
98 | {{ vnic.name }}
99 |
100 |
101 | MAC
102 | {{ vnic.mac }}
103 |
104 |
105 | Driver
106 | {{ vnic.driver }}
107 |
108 |
109 | Vlan ID
110 | {{ vnic.network.vlanId }}
111 |
112 |
113 |
114 | {% endfor %}
115 |
116 |
117 |
118 |
119 | {% endblock %}
--------------------------------------------------------------------------------
/vsphere/templates/resourcepool.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load multiply %}
3 | {% load divide %}
4 | {% load percent %}
5 | {% block title %}
6 | vSphere - {{ data.name }}
7 | {% endblock %}
8 | {% block content %}
9 | Statistics for Resource Pool {{ data.name }}
10 |
11 |
16 |
17 |
18 |
Total
19 |
20 |
21 | Memory
22 | {{ data.memory_sum | multiply:1048576 | filesizeformat }}
23 |
24 |
25 | Storage
26 | {{ data.storage_sum | multiply:1048576 | filesizeformat }}
27 |
28 |
29 | vCPU
30 | {{ data.vcpu_sum }}
31 |
32 |
33 |
34 |
35 |
Averages
36 |
37 |
38 |
39 |
40 | Minimum
41 | Maxium
42 | Average
43 | Deviation
44 |
45 |
46 |
47 |
48 | Memory
49 | {{ data.memory_min | multiply:1048576 | filesizeformat }}
50 | {{ data.memory_max | multiply:1048576 | filesizeformat }}
51 | {{ data.memory_avg | multiply:1048576 | filesizeformat }}
52 | {{ data.memory_dev | floatformat }}
53 |
54 |
55 | Storage
56 | {{ data.storage_min | multiply:1048576 | filesizeformat }}
57 | {{ data.storage_max | multiply:1048576 | filesizeformat }}
58 | {{ data.storage_avg | multiply:1048576 | filesizeformat }}
59 | {{ data.storage_dev | floatformat }}
60 |
61 |
62 | vCPU
63 | {{ data.vcpu_min }}
64 | {{ data.vcpu_max }}
65 | {{ data.vcpu_avg | floatformat }}
66 | {{ data.vcpu_dev | floatformat }}
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
Guest - {{ data.guests | length }} vm(s)
76 |
77 |
78 |
79 | Hostname
80 | Status
81 | Memory
82 | Disk
83 | vCPU
84 | Datacenter
85 |
86 |
87 |
88 | {% for guest in data.guests %}
89 |
90 | {{ guest.name }}
91 |
92 | {% if guest.poweredOn %}
93 |
94 |
95 |
96 | {% else %}
97 |
98 |
99 |
100 | {% endif %}
101 |
102 | {{ guest.memory | multiply:1048576 | filesizeformat }}
103 | {{ guest.get_disk_reserved | multiply:1048576 | filesizeformat }}
104 | {{ guest.vcpu }}
105 | {{ guest.hypervisor.datacenter }}
106 |
107 | {% endfor %}
108 |
109 |
110 |
111 |
112 |
153 | {% endblock %}
154 |
--------------------------------------------------------------------------------
/vsphere/models.py:
--------------------------------------------------------------------------------
1 | from django.core.validators import RegexValidator
2 | from django.db.models import Sum
3 | from django.db import models
4 | import re
5 |
6 | name_regex = re.compile(r'^[a-zA-Z0-9\-\_\.]+$')
7 |
8 |
9 | class Hypervisor(models.Model):
10 | name = models.CharField(max_length=100, unique=True,
11 | validators=[RegexValidator(regex=name_regex)])
12 | cpuModel = models.CharField(max_length=100, blank=True, null=True)
13 | numCpuPkgs = models.IntegerField()
14 | vendor = models.CharField(max_length=100, blank=True, null=True)
15 | model = models.CharField(max_length=100, blank=True, null=True)
16 | numCpuThreads = models.IntegerField()
17 | memorySize = models.IntegerField()
18 | numCpuCores = models.IntegerField()
19 | cpuMhz = models.IntegerField()
20 | numHBAs = models.IntegerField()
21 | numNics = models.IntegerField()
22 | productName = models.CharField(max_length=100, blank=True, null=True)
23 | productVersion = models.CharField(max_length=20, blank=True, null=True)
24 | annotation = models.CharField(max_length=100, blank=True, null=True)
25 | datacenter = models.CharField(max_length=100, unique=False,
26 | validators=[RegexValidator(regex=name_regex)])
27 |
28 | def __unicode__(self):
29 | return u'%s' % self.name
30 |
31 | def get_number_guest(self):
32 | guest_list = Guest.objects.filter(hypervisor=self)
33 | return len(guest_list)
34 |
35 | def get_datastores_size(self):
36 | ds_list = Datastore.objects.filter(hypervisor=self)
37 | capacity = 0
38 | for ds in ds_list:
39 | capacity += int(ds.capacity)
40 | return capacity
41 |
42 | def get_mem_reserved(self):
43 | guest_list = Guest.objects.filter(hypervisor=self)
44 | mem_reserved = 0
45 | for guest in guest_list:
46 | mem_reserved += int(guest.memory)
47 | return mem_reserved
48 | memoryReserved = property(get_mem_reserved)
49 |
50 | def get_disk_reserved(self):
51 | ds_list = Datastore.objects.filter(hypervisor=self)
52 | disk_reserved = 0
53 | for ds in ds_list:
54 | disk_reserved += Datastore.get_reserved(ds)
55 | return disk_reserved
56 | diskReserved = property(get_disk_reserved)
57 |
58 | def get_vcpu_reserved(self):
59 | guest_list = Guest.objects.filter(hypervisor=self)
60 | vcpu_reserved = 0
61 | for guest in guest_list:
62 | vcpu_reserved += int(guest.vcpu)
63 | return vcpu_reserved
64 | vcpuReserved = property(get_vcpu_reserved)
65 |
66 | def get_raw_disk_reserved(self):
67 | raw_disk_reserved = 0
68 | guest_list = Guest.objects.filter(hypervisor=self)
69 | for guest in guest_list:
70 | try:
71 | _temp = Disk.objects.filter(guest=guest, raw=True).aggregate(Sum('size'))
72 | raw_disk_reserved += _temp.get('size__sum')
73 | except:
74 | pass
75 | return raw_disk_reserved
76 |
77 |
78 | class Guest(models.Model):
79 | name = models.CharField(max_length=100, unique=True)
80 | poweredOn = models.BooleanField()
81 | vcpu = models.IntegerField()
82 | memory = models.IntegerField()
83 | resourcePool = models.CharField(max_length=100)
84 | annotation = models.CharField(max_length=100, blank=True, null=True)
85 | osVersion = models.CharField(max_length=100, blank=True, null=True)
86 | hypervisor = models.ForeignKey(Hypervisor, unique=False, null=False)
87 |
88 | def __unicode__(self):
89 | return u'%s.%s' % (self.hypervisor.name, self.name)
90 |
91 | def get_hypervisor_name(self):
92 | return self.hypervisor.name
93 |
94 | def get_disk_reserved(self, raw=''):
95 | if raw is False:
96 | disk_list = Disk.objects.filter(guest=self, raw=False)
97 | else:
98 | disk_list = Disk.objects.filter(guest=self)
99 | disk_reserved = 0
100 | for disk in disk_list:
101 | disk_reserved += int(disk.size)
102 | return disk_reserved
103 |
104 |
105 | class Datastore(models.Model):
106 | name = models.CharField(max_length=100)
107 | capacity = models.IntegerField()
108 | hypervisor = models.ForeignKey(Hypervisor, null=False)
109 |
110 | def __unicode__(self):
111 | return u'%s.%s' % (self.hypervisor.name, self.name)
112 |
113 | def get_reserved(self):
114 | vd_list = Disk.objects.filter(datastore=self)
115 | reserved = 0
116 | for vd in vd_list:
117 | if not vd.raw:
118 | reserved += int(vd.size)
119 | return reserved
120 |
121 | def get_guests(self):
122 | disk_list = Disk.objects.filter(datastore=self)
123 | list_guest = []
124 | for disk in disk_list:
125 | if disk.guest not in list_guest:
126 | list_guest.append(disk.guest)
127 | return list_guest
128 |
129 |
130 | class Disk(models.Model):
131 | name = models.CharField(max_length=100)
132 | size = models.IntegerField()
133 | guest = models.ForeignKey(Guest, null=False)
134 | datastore = models.ForeignKey(Datastore, null=True)
135 | raw = models.BooleanField(default=False)
136 | thin = models.BooleanField(default=False)
137 |
138 | def __unicode__(self):
139 | return u'%s' % self.name
140 |
141 |
142 | class Vswitch(models.Model):
143 | name = models.CharField(max_length=100)
144 | hypervisor = models.ForeignKey(Hypervisor, unique=False, null=False)
145 |
146 | def __unicode__(self):
147 | return u'%s' % self.name
148 |
149 |
150 | class Network(models.Model):
151 | name = models.CharField(max_length=100)
152 | vlanId = models.IntegerField()
153 | vswitch = models.ForeignKey(Vswitch, unique=False, null=False)
154 |
155 | def __unicode__(self):
156 | return u'%s.%s' % (self.vswitch, self.name)
157 |
158 | def get_virtualnics(self):
159 | vnic_list = VirtualNic.objects.filter(network=self)
160 | return vnic_list
161 |
162 |
163 | class Interface(models.Model):
164 | name = models.CharField(max_length=100)
165 | mac = models.CharField(max_length=100, blank=True, null=True)
166 | driver = models.CharField(max_length=100, blank=True, null=True)
167 | linkSpeed = models.IntegerField()
168 | vswitch = models.ForeignKey(Vswitch, unique=False, null=True)
169 | hypervisor = models.ForeignKey(Hypervisor, unique=False, null=False)
170 |
171 | def __unicode__(self):
172 | return u'%s.%s' % (self.hypervisor.name, self.name)
173 |
174 |
175 | class VirtualNic(models.Model):
176 | name = models.CharField(max_length=100)
177 | mac = models.CharField(max_length=100, blank=True, null=True)
178 | driver = models.CharField(max_length=100, blank=True, null=True)
179 | guest = models.ForeignKey(Guest, unique=False, null=False)
180 | network = models.ForeignKey(Network, unique=False, null=False)
181 |
182 | def __unicode__(self):
183 | return u'%s.%s' % (self.guest.name, self.name)
184 |
--------------------------------------------------------------------------------
/vsphere/templates/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
37 |
38 |
65 |
66 | {% block title %}{% endblock %}
67 |
68 |
69 |
70 |
71 |
113 |
114 |
115 |
116 |
117 |
121 |
122 |
Hypervisor
123 |
A hypervisor, also called a virtual machine manager , is a server than can hosts multiple guest instances called virtual machine.
124 |
125 |
Guest
126 |
A guest, also called a virtual machine or vm , is a virtual instance hosted on a hypervisor.
127 |
128 |
CPU Thread
129 |
A thread is merely an ordered sequence of instructions. A "multithreaded processor," is a processor that can execute multiple instruction streams simultaneously.
130 |
131 |
vCPU
132 |
A vcpu, is the short for virtual cpu . This is the representation of a CPU for the guest or the vm.
133 |
134 |
Consolidation
135 |
Consolidation is the number of virtual cpu (vcpu) per Physical Threads. (vcpu ÷ threads)
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | {% block content %}{% endblock %}
147 |
148 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/vsphere/templates/top10.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% block title %}
3 | vSphere - Top 10 Resource Pool
4 | {% endblock %}
5 | {% block content %}
6 |
7 |
Top 10 resources pool
8 |
9 |
10 |
32 |
33 |
242 | {% endblock %}
243 |
--------------------------------------------------------------------------------
/vsphere/templates/datacenter.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load divide %}
3 |
4 | {% block title %}
5 | vSphere - Datacenter Vision
6 | {% endblock %}
7 | {% block content %}
8 |
9 | Statistics by Datacenter
10 | {% for datacenter in data %}
11 |
12 |
13 |
14 |
15 | Statistics for {{ datacenter.datacenter }}
16 |
17 |
18 | {{ datacenter.hypervisor }} Hypervisors
19 |
20 |
21 |
22 |
46 |
47 |
48 |
281 | {% endfor%}
282 | {% endblock %}
283 |
--------------------------------------------------------------------------------
/vsphere/templates/stats_by_resourcepool.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% block title %}
3 | vSphere - By Resource Pool
4 | {% endblock %}
5 | {% block content %}
6 |
7 |
Reserved resources by Resource Pool
8 |
9 |
10 |
32 |
294 | {% endblock %}
295 |
--------------------------------------------------------------------------------
/vsphere/templates/hypervisor.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% load multiply %}
3 | {% load percent %}
4 | {% block title %}
5 | vSphere - {{ hypervisor.name }}
6 | {% endblock %}
7 | {% block content %}
8 |
9 | {{ hypervisor.name }}
10 |
11 |
12 |
13 |
14 |
General
15 |
16 |
17 |
Datacenter
18 |
{{ hypervisor.datacenter }}
19 |
20 |
21 |
Manufacturer
22 |
{{ hypervisor.vendor }}
23 |
24 |
25 |
Model
26 |
{{ hypervisor.model }}
27 |
28 |
29 |
CPU Cores
30 |
{{ hypervisor.numCpuCores }} CPUs x {{ hypervisor.cpuMhz }} MHz
31 |
32 |
33 |
Processor Type
34 |
{{ hypervisor.cpuModel }}
35 |
36 |
37 |
Processor Sockets
38 |
{{ hypervisor.numCpuPkgs }}
39 |
40 |
41 |
Cores per Socket
42 |
{{ hypervisor.numCpuCores }}
43 |
44 |
45 |
Logical Processors
46 |
{{ hypervisor.numCpuThreads }}
47 |
48 |
49 |
Number of NICs
50 |
{{ hypervisor.numNics }}
51 |
52 |
53 |
Number of HBAs
54 |
{{ hypervisor.numHBAs }}
55 |
56 |
57 |
Product
58 |
{{ hypervisor.productName }} - {{ hypervisor.productVersion }}
59 |
60 |
61 |
Notes
62 |
{{ hypervisor.annotation }}
63 |
64 |
65 |
66 |
67 |
68 |
69 |
Resources
70 |
71 |
72 | Memory: {{ hypervisor.memoryReserved | multiply:1048576 | filesizeformat }}
73 | / {{ hypervisor.memorySize | multiply:1048576 | filesizeformat }}
74 |
75 |
76 |
77 |
78 |
{{ hypervisor.memoryReserved|percent:hypervisor.memorySize }}%
85 |
86 |
87 |
88 |
89 |
90 | Datastores: {{ hypervisor.diskReserved | multiply:1048576 | filesizeformat }}
91 | / {{ hypervisor.get_datastores_size | multiply:1048576 | filesizeformat }}
92 |
93 |
94 |
95 |
96 |
{{ hypervisor.diskReserved|percent:hypervisor.get_datastores_size }}%
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
Interfaces - {{ interfaces | length }} Interfaces(s)
112 |
113 |
114 | {% for int in interfaces %}
115 |
118 | {% endfor %}
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
Storage - {{ datastores | length }} Datastore(s)
128 |
129 | {% for ds in datastores %}
130 |
131 |
132 | {{ ds.name }}
133 |
134 |
135 |
{{ ds.capacity | multiply:1048576 | filesizeformat }} Total
136 |
{{ ds.get_reserved | multiply:1048576 | filesizeformat }} Used
137 |
138 |
143 |
144 |
145 |
{{ ds.get_reserved|percent:ds.capacity }}%
152 |
153 |
154 |
155 | {% endfor %}
156 | {% if hypervisor.get_raw_disk_reserved %}
157 |
158 |
159 |
160 | Total Raw Space
161 |
162 |
163 |
{{ hypervisor.get_raw_disk_reserved | multiply:1048576 | filesizeformat }}
164 |
165 |
166 |
167 |
168 | {% endif %}
169 |
170 |
171 |
172 |
173 |
Network - {{ networks | length }} Network(s)
174 |
175 |
176 | {% for vs in vswitchs %}
177 |
178 |
179 | {{ vs.name }}
180 |
181 |
182 | {% for net in networks %}
183 | {% if net.vswitch.name == vs.name %}
184 |
185 |
186 |
{{ net.name }}
187 |
188 | {% if net.vlanId %}
189 | vlan: {{ net.vlanId }}
190 | {% endif %}
191 |
192 |
193 |
196 |
197 | {% endif %}
198 | {% endfor %}
199 |
200 |
201 |
202 | {% endfor %}
203 |
204 |
205 |
206 |
207 |
208 |
Guest - {{ hypervisor.get_number_guest }} vm(s)
209 |
210 |
211 |
212 | Hostname
213 | Status
214 | Resource Pool
215 | Memory
216 | Disk
217 | vCPU
218 |
219 |
220 |
221 | {% for guest in guests %}
222 |
223 | {{ guest.name }}
224 |
225 | {% if guest.poweredOn %}
226 |
227 |
228 |
229 | {% else %}
230 |
231 |
232 |
233 | {% endif %}
234 |
235 | {{ guest.resourcePool }}
236 | {{ guest.memory | multiply:1048576 | filesizeformat }}
237 | {{ guest.get_disk_reserved | multiply:1048576 | filesizeformat }}
238 | {{ guest.vcpu }}
239 |
240 |
241 | {% endfor %}
242 |
243 |
244 | {% endblock %}
--------------------------------------------------------------------------------
/vsphere/templates/physical.html:
--------------------------------------------------------------------------------
1 | {% extends "head.html" %}
2 | {% block title %}
3 | vSphere - Global Vision
4 | {% endblock %}
5 | {% block content %}
6 | Physical resources installed
7 |
8 |
13 |
18 |
23 | {% if is_raw %}
24 |
29 | {% endif %}
30 |
35 |
40 |
45 |
46 |
47 |
371 | {% endblock %}
372 |
--------------------------------------------------------------------------------
/tools/import_hypervisor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from pysphere import VIServer, MORTypes, VIProperty
3 | from optparse import OptionParser
4 | from vsphere.models import VirtualNic
5 | from vsphere.models import Hypervisor
6 | from vsphere.models import Datastore
7 | from vsphere.models import Interface
8 | from vsphere.models import Vswitch
9 | from vsphere.models import Network
10 | from vsphere.models import Guest
11 | from vsphere.models import Disk
12 | from os.path import expanduser
13 | from sys import exit
14 | import ConfigParser
15 | import re
16 |
17 |
18 | def vmware_connect(host, user, password):
19 | """Return a VIServer conneciont"""
20 | s = VIServer()
21 | s.connect(host, user, password)
22 | return s
23 |
24 |
25 | def get_disks(vm):
26 | """Return a list of disk dict with keys name, size, thin, raw, filename"""
27 | ret_val = []
28 |
29 | disks = [d for d in vm.properties.config.hardware.device
30 | if d._type == 'VirtualDisk' and d.backing._type in
31 | ['VirtualDiskFlatVer1BackingInfo',
32 | 'VirtualDiskFlatVer2BackingInfo',
33 | 'VirtualDiskRawDiskMappingVer1BackingInfo',
34 | 'VirtualDiskSparseVer1BackingInfo',
35 | 'VirtualDiskSparseVer2BackingInfo']]
36 |
37 | for disk in disks:
38 | name = disk.deviceInfo.label
39 | size = int(disk.deviceInfo.summary.replace(',', '').replace(' KB', ''))
40 | size /= 1024
41 | filename = disk.backing.fileName
42 | raw = thin = False
43 | if disk.backing._type == 'VirtualDiskRawDiskMappingVer1BackingInfo':
44 | raw = True
45 | if hasattr(disk.backing, "thinProvisioned"):
46 | thin = True
47 | ret_val.append({'name': name, 'size': size, 'thin': thin,
48 | 'raw': raw, 'filename': filename})
49 | return ret_val
50 |
51 |
52 | def get_datastores(server):
53 | """Return a list of datastore dict with keys name, capacity, freeSpace"""
54 | ret_val = []
55 | for ds_mor, name in server.get_datastores().items():
56 | props = VIProperty(server, ds_mor)
57 | capacity = props.summary.capacity / 1024 / 1024
58 | freeSpace = props.summary.freeSpace / 1024 / 1024
59 | ret_val.append({'name': name,
60 | 'capacity': capacity,
61 | 'freeSpace': freeSpace})
62 | return ret_val
63 |
64 |
65 | def get_networks(server):
66 | """Return a list a network dict with keys name, vlanId, vswitchName"""
67 | mor, name = server.get_hosts().items()[0]
68 | prop = VIProperty(server, mor)
69 | ret_val = []
70 | for network in prop.configManager.networkSystem.networkInfo.portgroup:
71 | name = network.spec.name
72 | vlanId = network.spec.vlanId
73 | vswitchName = network.spec.vswitchName
74 | ret_val.append({'name': name,
75 | 'vlanId': vlanId,
76 | 'vswitchName': vswitchName})
77 |
78 | return ret_val
79 |
80 |
81 | def get_interfaces(prop):
82 | """Return a list of interface dict with keys driver, linkSpeed, mac,
83 | name"""
84 | ret_val = []
85 | for interface in prop.configManager.networkSystem.networkInfo.pnic:
86 | name = interface.device
87 | mac = interface.mac
88 | driver = interface.driver
89 | try:
90 | linkSpeed = interface.linkSpeed.speedMb
91 | except:
92 | try:
93 | linkSpeed = interface.spec.linkSpeed.speedMb
94 | except:
95 | linkSpeed = 0
96 | ret_val.append({'name': name,
97 | 'mac': mac,
98 | 'driver': driver,
99 | 'linkSpeed': linkSpeed})
100 |
101 | return ret_val
102 |
103 |
104 | def get_vnics(vm):
105 | """Return a list of vnic dict with keys name, mac, type, network"""
106 | ret_val = []
107 | for v in vm.get_property("devices").values():
108 | if v.get('macAddress'):
109 | name = v.get('label')
110 | mac = v.get('macAddress')
111 | driver = v.get('type')
112 | network = v.get('summary')
113 | ret_val.append({'name': name,
114 | 'mac': mac,
115 | 'type': driver,
116 | 'network': network})
117 |
118 | return ret_val
119 |
120 |
121 | def get_vswitch(server):
122 | """Return a list of vswitch dict with keys name, nicDevice"""
123 | mor, name = server.get_hosts().items()[0]
124 | prop = VIProperty(server, mor)
125 | ret_val = []
126 | for v in prop.configManager.networkSystem.networkConfig.vswitch:
127 | name = v.name
128 | nicDevice = v.spec.bridge.nicDevice # this is a list
129 | ret_val.append({'name': name, 'nicDevice': nicDevice})
130 |
131 | return ret_val
132 |
133 |
134 | def get_guests(server):
135 | """Return a list of dict guest"""
136 |
137 | properties = [
138 | 'name',
139 | 'storage.perDatastoreUsage',
140 | 'config.hardware.memoryMB',
141 | 'config.hardware.numCPU'
142 | ]
143 | results = server._retrieve_properties_traversal(
144 | property_names=properties,
145 | obj_type=MORTypes.VirtualMachine
146 | )
147 |
148 | ret_val = []
149 | if not results:
150 | return ret_val
151 |
152 | for item in results:
153 | for p in item.PropSet:
154 | if p.Name == 'config.hardware.memoryMB':
155 | memory = int(p.Val)
156 | if p.Name == 'config.hardware.numCPU':
157 | vcpu = int(p.Val)
158 | if p.Name == 'name':
159 | name = p.Val
160 | try:
161 | vm = server.get_vm_by_name(name)
162 | except:
163 | poweredOn = False
164 | disks = {}
165 | osVersion = ''
166 | annotation = ''
167 | vnics = []
168 | resourcePool = 'Default'
169 | else:
170 | annotation = vm.properties.config.annotation
171 | osVersion = vm.get_property('guest_full_name')
172 | poweredOn = vm.is_powered_on()
173 | disks = get_disks(vm)
174 | vnics = get_vnics(vm)
175 | resourcePool = vm.get_resource_pool_name()
176 |
177 | ret_val.append({'name': name,
178 | 'vcpu': vcpu,
179 | 'memory': memory,
180 | 'disks': disks,
181 | 'vnics': vnics,
182 | 'poweredOn': poweredOn,
183 | 'resourcePool': resourcePool,
184 | 'annotation': annotation,
185 | 'osVersion': osVersion})
186 |
187 | return ret_val
188 |
189 |
190 | def get_hardware(server):
191 | """Return a hardware dict"""
192 |
193 | mor, name = server.get_hosts().items()[0]
194 | prop = VIProperty(server, mor)
195 | overallMemoryUsage = prop.summary.quickStats.overallMemoryUsage
196 | overallCpuUsage = prop.summary.quickStats.overallCpuUsage
197 | numCpuThreads = prop.summary.hardware.numCpuThreads
198 | productName = prop.summary.config.product.name
199 | productVersion = prop.summary.config.product.version
200 | numCpuCores = prop.summary.hardware.numCpuCores
201 | numCpuPkgs = prop.summary.hardware.numCpuPkgs
202 | cpuModel = prop.summary.hardware.cpuModel
203 | numHBAs = prop.summary.hardware.numHBAs
204 | numNics = prop.summary.hardware.numNics
205 | cpuMhz = prop.summary.hardware.cpuMhz
206 | memorySize = prop.hardware.memorySize
207 | vendor = prop.summary.hardware.vendor
208 | model = prop.summary.hardware.model
209 | interfaces = get_interfaces(prop)
210 | datastores = get_datastores(server)
211 |
212 | return {
213 | 'name': name,
214 | 'overallCpuUsage': overallCpuUsage,
215 | 'overallMemoryUsage': overallMemoryUsage,
216 | 'memorySize': memorySize / 1024 / 1024,
217 | 'cpuModel': ' '.join(cpuModel.split()),
218 | 'vendor': vendor,
219 | 'numCpuPkgs': numCpuPkgs,
220 | 'numCpuCores': numCpuCores,
221 | 'numCpuThreads': numCpuThreads,
222 | 'productName': productName,
223 | 'productVersion': productVersion,
224 | 'numNics': numNics,
225 | 'numHBAs': numHBAs,
226 | 'model': model,
227 | 'cpuMhz': cpuMhz,
228 | 'interfaces': interfaces,
229 | 'datastores': datastores,
230 | }
231 |
232 |
233 | def create_hypervisor(hypervisor, datacenter, note=''):
234 | """Create an Hypervisor object from get_hardware and a datacenter"""
235 | h = Hypervisor()
236 | h.name = hypervisor.get('name')
237 | h.cpuModel = hypervisor.get('cpuModel')
238 | h.numCpuPkgs = hypervisor.get('numCpuPkgs')
239 | h.vendor = hypervisor.get('vendor')
240 | h.numCpuThreads = hypervisor.get('numCpuThreads')
241 | h.memorySize = hypervisor.get('memorySize')
242 | h.numCpuCores = hypervisor.get('numCpuCores')
243 | h.cpuMhz = hypervisor.get('cpuMhz')
244 | h.numHBAs = hypervisor.get('numHBAs')
245 | h.numNics = hypervisor.get('numNics')
246 | h.productName = hypervisor.get('productName')
247 | h.productVersion = hypervisor.get('productVersion')
248 | h.annotation = note
249 | h.datacenter = datacenter
250 |
251 | h.clean()
252 | h.save()
253 | return h
254 |
255 |
256 | def create_datastore(datastore, hypervisor):
257 | """ Create a Datastore object from get_datastores and Hypervisor object"""
258 | d = Datastore()
259 | d.name = datastore.get('name')
260 | d.capacity = datastore.get('capacity')
261 | d.hypervisor_id = hypervisor.id
262 |
263 | d.clean()
264 | d.save()
265 | return d
266 |
267 |
268 | def create_guest(guest, hypervisor):
269 | """Create Guest object from get_guests and Hypervisor object"""
270 | g = Guest()
271 | g.name = guest.get('name')
272 | g.memory = guest.get('memory')
273 | g.poweredOn = guest.get('poweredOn')
274 | g.vcpu = guest.get('vcpu')
275 | g.resourcePool = guest.get('resourcePool')
276 | g.annotation = guest.get('annotation')
277 | g.osVersion = guest.get('osVersion')
278 | g.hypervisor = hypervisor
279 |
280 | g.clean()
281 | g.save()
282 | return g
283 |
284 |
285 | def create_disk(disk, datastore, guest):
286 | """Create a Disk object from get_disks, Datastore and Guest objects"""
287 | d = Disk()
288 | d.name = disk.get('name')
289 | d.size = disk.get('size')
290 | d.raw = disk.get('raw')
291 | d.guest = guest
292 | if not d.raw:
293 | d.datastore = datastore
294 |
295 | d.clean()
296 | d.save()
297 | return d
298 |
299 |
300 | def create_vswitch(vswitch, hypervisor):
301 | """Create a Vswitch object from get_vswitch"""
302 | v = Vswitch()
303 | v.name = vswitch.get('name')
304 | v.hypervisor = hypervisor
305 |
306 | v.clean()
307 | v.save()
308 | return v
309 |
310 |
311 | def create_network(network, vswitch):
312 | """Create a Network object from get_networks and a vswitch object"""
313 | n = Network()
314 | n.name = network.get('name')
315 | n.vlanId = network.get('vlanId')
316 | n.vswitch = vswitch
317 |
318 | n.clean()
319 | n.save()
320 | return n
321 |
322 |
323 | def create_interface(interface, hypervisor, vswitch=None):
324 | """Create an Interface object from get_interfaces,
325 | an Hypervisor and Vswitch objects"""
326 | i = Interface()
327 | i.name = interface.get('name')
328 | i.mac = interface.get('mac')
329 | i.driver = interface.get('driver')
330 | i.linkSpeed = interface.get('linkSpeed')
331 | if vswitch:
332 | i.vswitch = vswitch
333 | i.hypervisor = hypervisor
334 |
335 | i.clean()
336 | i.save()
337 | return i
338 |
339 |
340 | def create_vnic(vnic, guest, network):
341 | """Create a VirtualNic object from get_vnics, an Guest
342 | and a Network object"""
343 | v = VirtualNic()
344 | v.name = vnic.get('name')
345 | v.mac = vnic.get('mac')
346 | v.driver = vnic.get('type')
347 | v.guest = guest
348 | v.network = network
349 |
350 | v.clean()
351 | v.save()
352 | return v
353 |
354 |
355 | def create_full_hypervisor(server, datacenter, note):
356 | """Create a full hypervisor with Hardware, interface, network,
357 | guetst, ..."""
358 | HARDWARE = get_hardware(server)
359 | hypervisor = create_hypervisor(HARDWARE, datacenter, note)
360 |
361 | DATASTORES = HARDWARE.get('datastores')
362 | for ds in DATASTORES:
363 | create_datastore(ds, hypervisor)
364 |
365 | NETWORKS = get_networks(server)
366 | VSWITCHS = get_vswitch(server)
367 | for vswitch in VSWITCHS:
368 | create_vswitch(vswitch, hypervisor)
369 | for network in NETWORKS:
370 | n_vswitchName = network.get('vswitchName')
371 | n_vswitch = Vswitch.objects.get(name=n_vswitchName,
372 | hypervisor=hypervisor)
373 | create_network(network, n_vswitch)
374 |
375 | INTERFACES = HARDWARE.get('interfaces')
376 | for interface in INTERFACES:
377 | i_vs_name = ''
378 | i_name = interface.get('name')
379 | for x in VSWITCHS:
380 | if i_name in x.get('nicDevice'):
381 | i_vs_name = x.get('name')
382 | try:
383 | n_vswitch = Vswitch.objects.get(name=i_vs_name,
384 | hypervisor=hypervisor)
385 | except:
386 | create_interface(interface, hypervisor)
387 | else:
388 | create_interface(interface, hypervisor, n_vswitch)
389 |
390 | GUESTS = get_guests(server)
391 | for guest in GUESTS:
392 | g = create_guest(guest, hypervisor)
393 |
394 | DISKS = guest.get('disks')
395 | for disk in DISKS:
396 | disk_name = disk.get('filename')
397 | m = re.search(r"\[([A-Za-z0-9_]+)\]", disk_name)
398 | try:
399 | disk_ds_name = m.group(1)
400 | disk_ds = Datastore.objects.get(name=disk_ds_name,
401 | hypervisor=hypervisor)
402 | create_disk(disk, disk_ds, g)
403 | except:
404 | pass
405 |
406 | VNICS = guest.get('vnics')
407 | for vnic in VNICS:
408 | vnic_net_name = vnic.get('network')
409 | try:
410 | vnic_net = Network.objects.get(name=vnic_net_name,
411 | vswitch__hypervisor=hypervisor)
412 | create_vnic(vnic, g, vnic_net)
413 | except:
414 | pass
415 |
416 |
417 | if __name__ == '__main__':
418 | Config = ConfigParser.ConfigParser()
419 | Config.read(expanduser('~/.hypervisor.ini'))
420 |
421 | parser = OptionParser()
422 | parser.add_option('-H', '--hostname',
423 | help='Host name, IP Address - mandatory')
424 | parser.add_option('-u', '--user', default='root',
425 | help='User name [default: %default]')
426 | parser.add_option('-d', '--datacenter', default='',
427 | help='Datacenter [default: %default]')
428 | parser.add_option('-p', '--password', type='string', default='',
429 | help='Password to connect [default: %default]')
430 | parser.add_option('-a', '--anotation', type='string', default='',
431 | help='Hypervisor Note [default: %default]')
432 |
433 | (options, args) = parser.parse_args()
434 |
435 | mandatories = ['hostname', 'datacenter']
436 |
437 | for m in mandatories:
438 | if getattr(options, m) is None:
439 | print '"%s" option is missing' % m
440 | parser.print_help()
441 | exit(-1)
442 |
443 | try:
444 | password = Config.get(options.user, 'password')
445 | except:
446 | password = ''
447 |
448 | if getattr(options, 'password'):
449 | password = options.password
450 | if not password:
451 | print '"password" option is missing'
452 | exit(-1)
453 |
454 | user = options.user
455 | hostname = options.hostname
456 | datacenter = options.datacenter
457 | note = options.anotation
458 |
459 | try:
460 | server = vmware_connect(hostname, user, password)
461 | except:
462 | exit(1)
463 |
464 | create_full_hypervisor(server, datacenter, note)
465 |
466 | server.disconnect()
467 |
--------------------------------------------------------------------------------
/vsphere/views.py:
--------------------------------------------------------------------------------
1 | from vsphere.models import Hypervisor, Guest, Datastore, Disk, Interface, VirtualNic, Network, Vswitch
2 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
3 | from django.shortcuts import render_to_response
4 | from django.db.models import Min, Max, Avg, Sum
5 | from django.template import RequestContext
6 | from django.http import HttpResponse
7 |
8 |
9 | def list_deviation(l):
10 | import math
11 |
12 | def average(s):
13 | return sum(s) * 1.0 / len(s)
14 | avg = average(l)
15 | variance = map(lambda x: (x - avg)**2, l)
16 |
17 | standard_deviation = math.sqrt(average(variance))
18 | return standard_deviation
19 |
20 |
21 | def home(request):
22 | hypervisor_list = Hypervisor.objects.all()
23 | datacenter = [x.datacenter for x in hypervisor_list]
24 | datacenter = list(set(datacenter))
25 |
26 | ret_val = []
27 | for dc in datacenter:
28 | hypervisors = Hypervisor.objects.filter(datacenter=dc)
29 | num_vm = 0
30 | storage = 0
31 | storage_reserved = 0
32 | mem_reserved = 0
33 | mem = 0
34 | threads = 0
35 | vcpu_reserved = 0
36 | raw_storage_reserved = 0
37 | for hv in hypervisors:
38 | num_vm += hv.get_number_guest()
39 | storage += hv.get_datastores_size()
40 | storage_reserved += hv.diskReserved
41 | mem_reserved += hv.memoryReserved
42 | mem += hv.memorySize
43 | threads += hv.numCpuThreads
44 | vcpu_reserved += hv.vcpuReserved
45 | raw_storage_reserved += hv.get_raw_disk_reserved()
46 |
47 | used_storage = int(100 * storage_reserved / storage)
48 | used_mem = int(100 * mem_reserved / mem)
49 | cpu_consolidation = float(vcpu_reserved) / threads
50 |
51 | info = {'name': dc,
52 | 'nb_hv': len(hypervisors),
53 | 'nb_guest': num_vm,
54 | 'used_storage': used_storage,
55 | 'used_mem': used_mem,
56 | 'cpu_consolidation': cpu_consolidation,
57 | 'raw_storage_reserved': raw_storage_reserved,
58 | }
59 | ret_val.append(info)
60 |
61 | data = {
62 | 'datacenter': ret_val,
63 | }
64 | return render_to_response('home.html',
65 | data,
66 | context_instance=RequestContext(request))
67 |
68 |
69 | def resourcepools_info(request):
70 | guest_list = Guest.objects.all()
71 | resource_pool = [x.resourcePool for x in guest_list]
72 | resource_pool = list(set(resource_pool))
73 |
74 | ret_val = []
75 | for rp in resource_pool:
76 | guests = Guest.objects.filter(resourcePool=rp)
77 | num_vm = len(guests)
78 | mem_reserved = 0
79 | vcpu_reserved = 0
80 | disk_reserved = 0
81 | for guest in guests:
82 | mem_reserved += guest.memory
83 | vcpu_reserved += guest.vcpu
84 | disk_reserved += guest.get_disk_reserved(raw=False)
85 | info = {'name': rp,
86 | 'num_vm': num_vm,
87 | 'mem_reserved': mem_reserved,
88 | 'vcpu_reserved': vcpu_reserved,
89 | 'disk_reserved': disk_reserved,
90 | }
91 | ret_val.append(info)
92 |
93 | data = {
94 | 'resource_pool': ret_val,
95 | }
96 | return data
97 |
98 |
99 | def stats_by_resourcepool(request):
100 | data = resourcepools_info(request)
101 | return render_to_response('stats_by_resourcepool.html',
102 | data,
103 | context_instance=RequestContext(request))
104 |
105 |
106 | def top10(request):
107 | data = resourcepools_info(request)
108 | d = data['resource_pool']
109 | data['top10_mem'] = [x['name'] for x in sorted(d, key=lambda a: -a['mem_reserved'])][:10]
110 | data['top10_cpu'] = [x['name'] for x in sorted(d, key=lambda a: -a['vcpu_reserved'])][:10]
111 | data['top10_disk'] = [x['name'] for x in sorted(d, key=lambda a: -a['disk_reserved'])][:10]
112 |
113 | return render_to_response('top10.html',
114 | data,
115 | context_instance=RequestContext(request))
116 |
117 |
118 | def resourcepool_info(rp):
119 |
120 | guest_list = Guest.objects.filter(resourcePool=rp)
121 |
122 | memory_max = guest_list.filter(resourcePool=rp).aggregate(Max('memory'))
123 | memory_min = guest_list.filter(resourcePool=rp).aggregate(Min('memory'))
124 | memory_avg = guest_list.filter(resourcePool=rp).aggregate(Avg('memory'))
125 | memory_sum = guest_list.filter(resourcePool=rp).aggregate(Sum('memory'))
126 | memory_dev = list_deviation([x.memory for x in guest_list])
127 | vcpu_max = guest_list.filter(resourcePool=rp).aggregate(Max('vcpu'))
128 | vcpu_min = guest_list.filter(resourcePool=rp).aggregate(Min('vcpu'))
129 | vcpu_avg = guest_list.filter(resourcePool=rp).aggregate(Avg('vcpu'))
130 | vcpu_sum = guest_list.filter(resourcePool=rp).aggregate(Sum('vcpu'))
131 | vcpu_dev = list_deviation([x.vcpu for x in guest_list])
132 | storage_list = [x.get_disk_reserved() for x in guest_list]
133 | storage_max = max(storage_list)
134 | storage_min = min(storage_list)
135 | storage_avg = sum(storage_list) / float(len(storage_list))
136 | storage_sum = sum(storage_list)
137 | storage_dev = list_deviation(storage_list)
138 |
139 | dc_dict = {}
140 | for g in guest_list:
141 | dc = g.hypervisor.datacenter
142 | if dc not in dc_dict:
143 | dc_dict[dc] = 1
144 | else:
145 | dc_dict[dc] += 1
146 | dc_count_guest = []
147 | for dc in dc_dict:
148 | dc_count_guest.append({'name': dc, 'count': dc_dict.get(dc)})
149 |
150 | info = {
151 | 'name': rp,
152 | 'dc_count_guest': dc_count_guest,
153 | 'guests': guest_list,
154 | 'memory_max': memory_max.get('memory__max'),
155 | 'memory_min': memory_min.get('memory__min'),
156 | 'memory_avg': memory_avg.get('memory__avg'),
157 | 'memory_sum': memory_sum.get('memory__sum'),
158 | 'memory_dev': memory_dev,
159 | 'vcpu_max': vcpu_max.get('vcpu__max'),
160 | 'vcpu_min': vcpu_min.get('vcpu__min'),
161 | 'vcpu_avg': vcpu_avg.get('vcpu__avg'),
162 | 'vcpu_sum': vcpu_sum.get('vcpu__sum'),
163 | 'vcpu_dev': vcpu_dev,
164 | 'storage_max': storage_max,
165 | 'storage_min': storage_min,
166 | 'storage_avg': storage_avg,
167 | 'storage_sum': storage_sum,
168 | 'storage_dev': storage_dev,
169 | }
170 |
171 | return info
172 |
173 |
174 | def resourcepool(request):
175 | rp = request.GET.get('name')
176 | info = resourcepool_info(rp)
177 | data = {
178 | 'data': info,
179 | }
180 | return render_to_response('resourcepool.html',
181 | data,
182 | context_instance=RequestContext(request))
183 |
184 |
185 | def resourcepool_info_list(rp):
186 | info = resourcepool_info(rp)
187 | return {
188 | 'name': rp,
189 | 'guests': info.get('guests'),
190 | 'memory_avg': info.get('memory_avg'),
191 | 'storage_avg': info.get('storage_avg'),
192 | 'vcpu_avg': info.get('vcpu_avg'),
193 | }
194 |
195 |
196 | def resourcepools(request):
197 | rp_list = [g.resourcePool for g in Guest.objects.all()]
198 | rp_list = list(set(rp_list))
199 |
200 | data = []
201 | for rp in rp_list:
202 | info = resourcepool_info_list(rp)
203 | data.append(info)
204 |
205 | paginator = Paginator(data, 25)
206 |
207 | page = request.GET.get('page')
208 | try:
209 | data_pag = paginator.page(page)
210 | except PageNotAnInteger:
211 | data_pag = paginator.page(1)
212 | except EmptyPage:
213 | data_pag = paginator.page(paginator.num_pages)
214 |
215 | data = {
216 | 'resourcepool_list': data_pag,
217 | }
218 |
219 | return render_to_response('resourcepools.html',
220 | data,
221 | context_instance=RequestContext(request))
222 |
223 |
224 | def hypervisors(request):
225 | hypervisor_list = Hypervisor.objects.all()
226 | hypervisor_list_sorted = sorted(hypervisor_list,
227 | key=lambda a: (a.memoryReserved - a.memorySize,
228 | a.diskReserved - a.get_datastores_size()))
229 | paginator = Paginator(hypervisor_list_sorted, 25)
230 |
231 | page = request.GET.get('page')
232 | try:
233 | hypervisors_pag = paginator.page(page)
234 | except PageNotAnInteger:
235 | hypervisors_pag = paginator.page(1)
236 | except EmptyPage:
237 | hypervisors_pag = paginator.page(paginator.num_pages)
238 |
239 | data = {
240 | 'hypervisor_list': hypervisors_pag,
241 | }
242 | return render_to_response('hypervisors.html',
243 | data,
244 | context_instance=RequestContext(request))
245 |
246 |
247 | def guests(request):
248 | guest_list = Guest.objects.all()
249 | guest_list = guest_list.order_by('name')
250 | paginator = Paginator(guest_list, 25)
251 |
252 | page = request.GET.get('page')
253 | try:
254 | guests = paginator.page(page)
255 | except PageNotAnInteger:
256 | guests = paginator.page(1)
257 | except EmptyPage:
258 | guests = paginator.page(paginator.num_pages)
259 |
260 | data = {
261 | 'guest_list': guests,
262 | }
263 | return render_to_response('guests.html',
264 | data,
265 | context_instance=RequestContext(request))
266 |
267 |
268 | def guest_info(request):
269 | if 'name' in request.GET and request.GET['name']:
270 | guest_name = request.GET['name']
271 | guest = Guest.objects.filter(name=guest_name)
272 | disks = Disk.objects.filter(guest=guest[0])
273 | vnics = VirtualNic.objects.filter(guest=guest[0])
274 | data = {
275 | 'guest': guest[0],
276 | 'disks': disks,
277 | 'vnics': vnics,
278 | }
279 | return render_to_response('guest.html',
280 | data,
281 | context_instance=RequestContext(request))
282 | else:
283 | return HttpResponse('Please submit something !')
284 |
285 |
286 | def hypervisor_info(request):
287 | if 'name' in request.GET and request.GET['name']:
288 | hypervisor_name = request.GET['name']
289 | hypervisor = Hypervisor.objects.filter(name=hypervisor_name)
290 | guests = Guest.objects.filter(hypervisor=hypervisor[0])
291 | datastores = Datastore.objects.filter(hypervisor=hypervisor[0])
292 | interfaces = Interface.objects.filter(hypervisor=hypervisor[0])
293 | vswitchs = Vswitch.objects.filter(hypervisor=hypervisor[0])
294 | networks = Network.objects.filter(vswitch__hypervisor=hypervisor[0])
295 |
296 | data = {
297 | 'hypervisor': hypervisor[0],
298 | 'guests': guests,
299 | 'datastores': datastores.order_by('name'),
300 | 'interfaces': interfaces,
301 | 'vswitchs': vswitchs,
302 | 'networks': networks,
303 | }
304 | return render_to_response('hypervisor.html',
305 | data,
306 | context_instance=RequestContext(request))
307 | else:
308 | return HttpResponse('Please submit something !')
309 |
310 |
311 | def search(request):
312 | if 'filter' in request.GET and request.GET['filter']:
313 | field = request.GET['filter']
314 | hypervisor_list = Hypervisor.objects.filter(name__icontains=field)
315 | guest_list = Guest.objects.filter(name__icontains=field)
316 | resourcepool_list = [g.resourcePool for g in Guest.objects.all()]
317 | resourcepool_list = list(set(resourcepool_list))
318 |
319 | data = []
320 | for rp in [rp for rp in resourcepool_list if field.lower() in rp.lower()]:
321 | info = resourcepool_info_list(rp)
322 | data.append(info)
323 |
324 | data = {
325 | 'hypervisor_list': hypervisor_list,
326 | 'guest_list': guest_list,
327 | 'resourcepool_list': data,
328 | }
329 | return render_to_response('search.html',
330 | data,
331 | context_instance=RequestContext(request))
332 | else:
333 | return HttpResponse('Please submit something !')
334 |
335 |
336 | def interface_statistics(hv):
337 | inter_list = Interface.objects.filter(
338 | hypervisor=hv).exclude(vswitch=None)
339 | ret_val = {}
340 | for i in inter_list:
341 | if i.linkSpeed in ret_val:
342 | ret_val[i.linkSpeed] += 1
343 | else:
344 | ret_val[i.linkSpeed] = 1
345 |
346 | return ret_val
347 |
348 |
349 | def sum_list_dict(l):
350 | ret_val = {}
351 | for d in l:
352 | for k, v in d.items():
353 | if k not in ret_val:
354 | ret_val[k] = v
355 | else:
356 | ret_val[k] += v
357 | return ret_val
358 |
359 |
360 | def datacenter_info(request):
361 | hypervisor_list = Hypervisor.objects.all()
362 | ret_val = {}
363 | for hv in hypervisor_list:
364 | datacenter = hv.datacenter
365 | if datacenter not in ret_val:
366 | ret_val[datacenter] = {'threads': 0, 'vcpu_reserved': 0,
367 | 'memory': 0, 'mem_reserved': 0, 'guest': 0,
368 | 'hypervisor': 0, 'storage': 0,
369 | 'esxiversion': [], 'disk_reserved': 0,
370 | 'linkspeed': [], 'raw': 0}
371 | ret_val[datacenter]['hypervisor'] += 1
372 | ret_val[datacenter]['threads'] += hv.numCpuThreads
373 | ret_val[datacenter]['vcpu_reserved'] += hv.vcpuReserved
374 | ret_val[datacenter]['memory'] += hv.memorySize
375 | ret_val[datacenter]['mem_reserved'] += hv.memoryReserved
376 | ret_val[datacenter]['storage'] += hv.get_datastores_size()
377 | ret_val[datacenter]['disk_reserved'] += hv.diskReserved
378 | ret_val[datacenter]['raw'] += hv.get_raw_disk_reserved()
379 | ret_val[datacenter]['guest'] += hv.get_number_guest()
380 | ret_val[datacenter]['linkspeed'].append(interface_statistics(hv))
381 | ret_val[datacenter]['esxiversion'].append({str(hv.productVersion): 1})
382 |
383 | datacenter = []
384 | for dc in ret_val:
385 | datacenter.append({
386 | 'datacenter': dc,
387 | 'hypervisor': ret_val[dc]['hypervisor'],
388 | 'storage': ret_val[dc]['storage'],
389 | 'threads': ret_val[dc]['threads'],
390 | 'guest': ret_val[dc]['guest'],
391 | 'vcpu_reserved': ret_val[dc]['vcpu_reserved'],
392 | 'mem_reserved': ret_val[dc]['mem_reserved'],
393 | 'disk_reserved': ret_val[dc]['disk_reserved'],
394 | 'raw': ret_val[dc]['raw'],
395 | 'memory': ret_val[dc]['memory'],
396 | 'linkspeed': reduce(lambda x, y: dict((k, v + y[k])
397 | for k, v in x.iteritems()),
398 | ret_val[dc]['linkspeed']),
399 | 'esxiversion': sum_list_dict(ret_val[dc]['esxiversion']),
400 | })
401 | data = {
402 | 'data': datacenter,
403 | }
404 | return data
405 |
406 |
407 | def physical_statistics(request):
408 | data = datacenter_info(request)
409 | data['esxiversion'] = sum_list_dict([x['esxiversion'] for x in data['data']])
410 | data['linkspeed'] = sum_list_dict([x['linkspeed'] for x in data['data']])
411 | data['is_raw'] = False
412 | for x in data['data']:
413 | if x.get('raw') > 0:
414 | data['is_raw'] = True
415 |
416 | return render_to_response('physical.html', data,
417 | context_instance=RequestContext(request))
418 |
419 |
420 | def datacenter_statistics(request):
421 | data = datacenter_info(request)
422 | guest_list = Guest.objects.all()
423 |
424 | guest_rp_dc = {}
425 | for guest in guest_list:
426 | rp = guest.resourcePool
427 | dc = guest.hypervisor.datacenter
428 | if dc not in guest_rp_dc.keys():
429 | guest_rp_dc[dc] = {}
430 | if rp not in guest_rp_dc[dc]:
431 | guest_rp_dc[dc][rp] = 0
432 |
433 | guest_rp_dc[dc][rp] += 1
434 | u = []
435 | for dc in guest_rp_dc:
436 | temp = guest_rp_dc[dc]
437 | temp['name'] = dc
438 | u.append(temp)
439 | data['guest_rp_dc'] = u
440 | return render_to_response('datacenter.html', data,
441 | context_instance=RequestContext(request))
442 |
--------------------------------------------------------------------------------