diff --git a/dashboard/api/windc.py b/dashboard/api/windc.py index 16f289b..adf6059 100644 --- a/dashboard/api/windc.py +++ b/dashboard/api/windc.py @@ -24,7 +24,6 @@ import urlparse from django.utils.decorators import available_attrs from portasclient.v1.client import Client as windc_client - LOG = logging.getLogger(__name__) @@ -52,28 +51,78 @@ def datacenters_list(request): return windcclient(request).environments.list() +def datacenters_deploy(request, datacenter_id): + sessions = windcclient(request).sessions.list(datacenter_id) + for session in sessions: + if session.state == 'open': + session_id = session.id + if not session_id: + return "Sorry, nothing to deploy." + return windcclient(request).sessions.deploy(datacenter_id, session_id) + + +def datacenters_get_status(request, datacenter_id): + return datacenters_get(request, datacenter_id).status + + def services_create(request, datacenter, parameters): - return windcclient(request).services.create(datacenter, parameters) + session_id = windcclient(request).sessions.list(datacenter)[0].id + if parameters['service_type'] == 'Active Directory': + res = windcclient(request).activeDirectories.create(datacenter, + session_id, + parameters) + else: + res = windcclient(request).webServers.create(datacenter, + session_id, + parameters) + + return res -def services_list(request, datacenter): - LOG.critical("********************************") - LOG.critical(dir(windcclient(request))) - LOG.critical("********************************") - session_id = request.user.token.token['id'] - services = [] - services += windcclient(request).activeDirectories.list(datacenter, session_id) - #services += windcclient(request).webServers.list(datacenter) - +def services_list(request, datacenter_id): + session_id = None + sessions = windcclient(request).sessions.list(datacenter_id) + for s in sessions: + if s.state in ['open', 'deployed', 'deploying']: + session_id = s.id + + if session_id is None: + session_id = windcclient(request).sessions.configure(datacenter_id).id + + services = windcclient(request).activeDirectories.list(datacenter_id, + session_id) + services += windcclient(request).webServers.list(datacenter_id, session_id) + return services -def services_get(request, datacenter, service_id): - LOG.critical("********************************") - LOG.debug(parameters) - LOG.critical("********************************") - return windcclient(request).services.get(datacenter, service_id) +def services_get(request, datacenter_id, service_id): + services = services_list(request, datacenter_id) + + for service in services: + if service.id is service_id: + return service -def services_delete(request, datacenter, service_id): - return windcclient(request).services.delete(datacenter, service_id) +def services_delete(request, datacenter_id, service_id): + services = services_list(request, datacenter_id) + + session_id = None + sessions = windcclient(request).sessions.list(datacenter_id) + for session in sessions: + if session.state == 'open': + session_id = session.id + + if session_id is None: + raise Exception("Sorry, you can not delete this service now.") + + for service in services: + if service.id is service_id: + if service.type is 'Active Directory': + windcclient(request).activeDirectories.delete(datacenter_id, + session_id, + service_id) + elif service.type is 'IIS': + windcclient(request).webServers.delete(datacenter_id, + session_id, + service_id) diff --git a/dashboard/windc/forms.py b/dashboard/windc/forms.py index 7340fb2..b44cd16 100644 --- a/dashboard/windc/forms.py +++ b/dashboard/windc/forms.py @@ -19,6 +19,7 @@ # under the License. import logging +import string from django import forms from django.core.urlresolvers import reverse @@ -30,82 +31,90 @@ from horizon import forms from horizon import exceptions from horizon import messages -import pdb - LOG = logging.getLogger(__name__) +class PasswordField(forms.CharField): + + # Setup the Field + def __init__(self, label, *args, **kwargs): + super(PasswordField, self).__init__(min_length=7, required=True, + label=label, + widget=forms.PasswordInput(render_value=False), + *args, **kwargs) + + def clean(self, value): + + # Setup Our Lists of Characters and Numbers + characters = list(string.letters) + special_characters = '!@#$%^&*()_+|\/.,~?><:{}' + numbers = [str(i) for i in range(10)] + + # Assume False until Proven Otherwise + numCheck = False + charCheck = False + specCharCheck = False + + # Loop until we Match + for char in value: + if not charCheck: + if char in characters: + charCheck = True + if not specCharCheck: + if char in special_characters: + specCharCheck = True + if not numCheck: + if char in numbers: + numCheck = True + if numCheck and charCheck and specCharCheck: + break + + if not numCheck or not charCheck or not specCharCheck: + raise forms.ValidationError(u'Your password must include at least \ + one letter, at least one number and \ + at least one special character.') + + return super(PasswordField, self).clean(value) + + class WizardFormServiceType(forms.Form): - service = forms.ChoiceField(label=_("Service Type"), + service = forms.ChoiceField(label=_('Service Type'), choices=[ - ('active directory', 'Active Directory'), - ('iis', 'Internet Information Services') + ('Active Directory', 'Active Directory'), + ('IIS', 'Internet Information Services') ]) class WizardFormConfiguration(forms.Form): - "The functions for this class will dynamically create in views.py" + 'The functions for this class will dynamically create in views.py' pass class WizardFormADConfiguration(forms.Form): - dc_name = forms.CharField(label=_("Domain Name"), - required=False) + dc_name = forms.CharField(label=_('Domain Name'), + required=True) - dc_count = forms.IntegerField(label=_("Instances Count"), + dc_count = forms.IntegerField(label=_('Instances Count'), required=True, min_value=1, max_value=100, initial=1) - adm_password = forms.CharField(widget=forms.PasswordInput, - label=_("Administrator password"), - required=False) + adm_password = PasswordField(_('Administrator password')) - recovery_password = forms.CharField(widget=forms.PasswordInput, - label=_("Recovery password"), - required=False) + recovery_password = PasswordField(_('Recovery password')) class WizardFormIISConfiguration(forms.Form): - iis_name = forms.CharField(label=_("IIS Server Name"), - required=False) + iis_name = forms.CharField(label=_('IIS Server Name'), + required=True) - adm_password = forms.CharField(widget=forms.PasswordInput, - label=_("Administrator password"), - required=False) + adm_password = PasswordField(_('Administrator password')) - iis_count = forms.IntegerField(label=_("IIS Servers Count"), - required=True, - min_value=1, - max_value=100, - initial=1) + iis_domain = forms.CharField(label=_('Member of the Domain'), + required=True) - iis_domain = forms.CharField(label=_("Member of the Domain"), - required=False) + domain_user_name = forms.CharField(label=_('Domain User Name'), + required=True) - domain_user_name = forms.CharField(label=_("Domain User Name"), - required=False) - - domain_user_password = forms.CharField(widget=forms.PasswordInput, - label=_("Domain User Password"), - required=False) - - -class UpdateWinDC(forms.SelfHandlingForm): - tenant_id = forms.CharField(widget=forms.HiddenInput) - data_center = forms.CharField(widget=forms.HiddenInput) - name = forms.CharField(required=True) - - def handle(self, request, data): - try: - server = api.nova.server_update(request, data['data_center'], - data['name']) - messages.success(request, - _('Data Center "%s" updated.') % data['name']) - return server - except: - redirect = reverse("horizon:project:windc:index") - exceptions.handle(request, - _('Unable to update data center.'), - redirect=redirect) + domain_user_password = PasswordField(_('Domain User Password')) diff --git a/dashboard/windc/tables.py b/dashboard/windc/tables.py index a5c7b4d..97fe9bc 100644 --- a/dashboard/windc/tables.py +++ b/dashboard/windc/tables.py @@ -43,24 +43,23 @@ LOG = logging.getLogger(__name__) class CreateService(tables.LinkAction): - name = "CreateService" - verbose_name = _("Create Service") - url = "horizon:project:windc:create" - classes = ("btn-launch", "ajax-modal") + name = 'CreateService' + verbose_name = _('Create Service') + url = 'horizon:project:windc:create' + classes = ('btn-launch', 'ajax-modal') def allowed(self, request, datum): return True def action(self, request, service): - # FIX ME api.windc.services_create(request, service) class CreateDataCenter(tables.LinkAction): - name = "CreateDataCenter" - verbose_name = _("Create Windows Data Center") - url = "horizon:project:windc:create_dc" - classes = ("btn-launch", "ajax-modal") + name = 'CreateDataCenter' + verbose_name = _('Create Windows Data Center') + url = 'horizon:project:windc:create_dc' + classes = ('btn-launch', 'ajax-modal') def allowed(self, request, datum): return True @@ -70,11 +69,11 @@ class CreateDataCenter(tables.LinkAction): class DeleteDataCenter(tables.BatchAction): - name = "delete" - action_present = _("Delete") - action_past = _("Delete") - data_type_singular = _("Data Center") - data_type_plural = _("Data Center") + name = 'delete' + action_present = _('Delete') + action_past = _('Delete') + data_type_singular = _('Data Center') + data_type_plural = _('Data Center') classes = ('btn-danger', 'btn-terminate') def allowed(self, request, datum): @@ -85,93 +84,128 @@ class DeleteDataCenter(tables.BatchAction): class DeleteService(tables.BatchAction): - name = "delete" - action_present = _("Delete") - action_past = _("Delete") - data_type_singular = _("Service") - data_type_plural = _("Service") + name = 'delete' + action_present = _('Delete') + action_past = _('Delete') + data_type_singular = _('Service') + data_type_plural = _('Service') classes = ('btn-danger', 'btn-terminate') def allowed(self, request, datum): return True def action(self, request, service_id): - ############## FIX ME: link = request.__dict__['META']['HTTP_REFERER'] datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1] - ############## - api.windc.services_delete(request, datacenter_id, service_id) + try: + api.windc.services_delete(request, datacenter_id, service_id) + except: + messages.error(request, + _('Sorry, you can not delete this service right now.')) -class EditService(tables.LinkAction): - name = "edit" - verbose_name = _("Edit") - url = "horizon:project:windc:update" - classes = ("ajax-modal", "btn-edit") +class DeployDataCenter(tables.BatchAction): + name = 'deploy' + action_present = _('Deploy') + action_past = _('Deploy') + data_type_singular = _('Data Center') + data_type_plural = _('Data Center') + classes = ('btn-launch') - def allowed(self, request, instance): + def allowed(self, request, datum): return True + def action(self, request, datacenter_id): + return api.windc.datacenters_deploy(request, datacenter_id) + class ShowDataCenterServices(tables.LinkAction): - name = "edit" - verbose_name = _("Services") - url = "horizon:project:windc:services" + name = 'edit' + verbose_name = _('Services') + url = 'horizon:project:windc:services' def allowed(self, request, instance): return True -class UpdateRow(tables.Row): +class UpdateDCRow(tables.Row): ajax = True - def get_data(self, request, instance_id): - instance = api.nova.server_get(request, instance_id) - instance.full_flavor = api.nova.flavor_get(request, - instance.flavor["id"]) - return instance + def get_data(self, request, datacenter_id): + return api.windc.datacenters_get(request, datacenter_id) + + +class UpdateServiceRow(tables.Row): + ajax = True + def get_data(self, request, service_id): + link = request.__dict__['META']['HTTP_REFERER'] + datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1] -class WinDCTable(tables.DataTable): - name = tables.Column("name", - link=("horizon:project:windc:services"), - verbose_name=_("Name")) - - class Meta: - name = "windc" - verbose_name = _("Windows Data Centers") - row_class = UpdateRow - table_actions = (CreateDataCenter,) - row_actions = (ShowDataCenterServices, DeleteDataCenter) + return api.windc.services_get(request, datacenter_id, service_id) STATUS_DISPLAY_CHOICES = ( - ("create", "Deploy"), + ('draft', 'Ready to deploy'), + ('pending', 'Wait for configuration'), + ('inprogress', 'Deploy in progress'), + ('finished', 'Active') ) +STATUS_CHOICES = ( + (None, True), + ('Ready to deploy', False), + ('Wait for configuration', True), + ('Deploy in progress', True), + ('Active', False), + ('error', False), +) -class WinServicesTable(tables.DataTable): +def get_datacenter_status(datacenter): + return datacenter.status - STATUS_CHOICES = ( - (None, True), - ("deployed", True), - ("active", True), - ("error", False), - ) +def get_service_status(service): + return service.status - name = tables.Column('dc_name', verbose_name=_('Name'), - link=("horizon:project:windc:service_details"),) - _type = tables.Column('type', verbose_name=_('Type')) - status = tables.Column('status', verbose_name=_('Status'), + +class WinDCTable(tables.DataTable): + + name = tables.Column('name', + link=('horizon:project:windc:services'), + verbose_name=_('Name')) + + status = tables.Column(get_datacenter_status, verbose_name=_('Status'), status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) class Meta: - name = "services" - verbose_name = _("Services") - row_class = UpdateRow + name = 'windc' + verbose_name = _('Windows Data Centers') + row_class = UpdateDCRow status_columns = ['status'] + table_actions = (CreateDataCenter,) + row_actions = (ShowDataCenterServices, DeleteDataCenter, + DeployDataCenter) + + +class WinServicesTable(tables.DataTable): + + name = tables.Column('name', verbose_name=_('Name'), + link=('horizon:project:windc:service_details'),) + + _type = tables.Column('service_type', verbose_name=_('Type')) + + status = tables.Column(get_service_status, verbose_name=_('Status'), + status=True, + status_choices=STATUS_CHOICES, + display_choices=STATUS_DISPLAY_CHOICES) + + class Meta: + name = 'services' + verbose_name = _('Services') + status_columns = ['status'] + row_class = UpdateServiceRow table_actions = (CreateService,) - row_actions = (EditService, DeleteService) + row_actions = (DeleteService,) diff --git a/dashboard/windc/templates/windc/_services_tabs.html b/dashboard/windc/templates/windc/_services_tabs.html index a00c4c3..a58eac8 100644 --- a/dashboard/windc/templates/windc/_services_tabs.html +++ b/dashboard/windc/templates/windc/_services_tabs.html @@ -7,6 +7,11 @@ {% block modal-header %}{% trans "Create Service" %}{% endblock %} {% block modal-body %} +
{% trans "Now you can set the parameters for Active Directory Service." %}
+{% trans "You can create few Active Directory instances, in this case will be created one Main Active Directory server and few Secondary Active Directory servers." %}
+{% trans "The DNS service will be automatically created on each Active Directory servers." %}
+ {% else %} +{% trans "Now you can set parameters for IIS Service." %}
+{% trans "The IIS Service - it is the server with complex Internet Information Services infrastructure, which included to the domain infrasructure." %}
+{% trans "Please, set the complex password for local administrator account." %}
+{% trans "Also, you can add this IIS server to the existing domain and configure credentials for domain user." %}
+ {% endif %} + + {% else %} +{% trans "Now you can select the type of the service." %}
+{% trans "The Active Directory Service allows to configure Domain Controllers with Active Directory and DNS infrastructure. You can create one Main Domain Controller and few Secondary Domain Controllers." %}
+{% trans "The Internet Information Services allows to configure IIS servers, which can be included to the existing domain infrastructure." %}
+ {% endif %} +