Cherry-pick the following change-ids from release-0.2.
I08b8b7391e591d0131af8c4fe074ddaf0222eddc I9eab7412b67b1cf83025688dba8d879aa0be3b01 I487019103d4ad00c993a6e2df0962dea68c4c86b I8d8463e79675778f6a8dc01623c81227d06e8d4b I6609d418150053ee4953a2ae9dba80f76da03fb2 Ic496352384412e53860ee48d696d2794b06ad2ca I2ae97838ac45eac65032f71f9f6e9445974f0236 I35279696b2aee81739a5c4cb7657e4a9fc4f52e2 Ia6b32e14213b147881b242710ca130a4dea3cdb2 I25ff8448c3cde53aa69905ba5f3736a37e7ed692 Icc1651aeed02784b8a3bde792550efb067af19c9 Ibd5529e1b1754b12fcfade77361dc393cc1780ab Ice7a3cca2f7931c6f9089f207eddb6f1f802bf4e I283a67e437d1495257e4c39b18e558072875ffea I10d4bfd2a0a6a35dbb3e9fca437ceae9e853cc1b I6c48f803b57399604211ad9a9faee44d87d4dd6d I7ae888d2708ca438f7e5c94a53e7ddbcc134f4f6 I6b7c54e3700b3b2511f87dfb107d91a13dee9d9b I2e5c1a4edea567fc2aa31541e7fbc582fc63b885 Ia2d2eaa17c6f8c3e53da4745b03a2b27ff6738fe I20f03d21c09d090b7edb3360da385e12cad28102 I932674e2b789be54c4366a9a2b81ceaa0c37a133 I64000e26965e8fabb883e5b1294b7639bdade849 I2093b4ed5c33340904698e0d0f01128ece7a2f2b I2c1e5e156bba1c4c4ed1cd5fb643410c24055706 Iebfe935385a3eeab2ea258bd8dad2ccb70ab14ef Id7b215a610c0c3375055fb1ff7c75e384fab2d3a Ie74f5a48ce90e3dab33cd3fc8b57a366433d7fe5 I136eb043e915d4028d5256efbb071c61906a3f69 I4fc13f58f679893b68abbc87c2650743c0258260 Idde251b1c7b1a31cadb5f416f753e365fe572961 Icd385908dd620837b0f4c779059ff540e10263df I29e4ef69087a78a85d9ea323590e70b0fc8ad642 I2f284035fc656a48c1c7525724a34a3b75f72c64 Ie46f5d27f21f6ddfc1e2cb86e081bea14e1099f4 Change-Id: I96cb8ee13e2905fab9ba41b6dea1ae84b74c7765
This commit is contained in:
parent
271e8de71d
commit
e9f38c707d
@ -1,6 +1,6 @@
|
||||
recursive-include muranodashboard/static *
|
||||
recursive-include muranodashboard/templates *
|
||||
include muranodashboard/panel/services/*.yaml
|
||||
include muranodashboard/services/*.yaml
|
||||
include tools/pip-requires
|
||||
include run_tests.sh
|
||||
include ChangeLog
|
||||
|
@ -53,8 +53,8 @@ class RadioColumn(Column):
|
||||
|
||||
class NodeDataGrid(DataGrid):
|
||||
name = Column('Node', sortable=False)
|
||||
is_sync = CheckColumn('Sync')
|
||||
is_primary = RadioColumn('Primary')
|
||||
isSync = CheckColumn('Sync')
|
||||
isMaster = RadioColumn('Primary')
|
||||
|
||||
def __init__(self, request, data):
|
||||
self.pk = PK()
|
||||
@ -68,7 +68,7 @@ class NodeDataGrid(DataGrid):
|
||||
super(NodeDataGrid, self).__init__(request, FakeQuerySet(
|
||||
Node, items=items), optimize_sorts=False)
|
||||
self.default_sort = []
|
||||
self.default_columns = ['name', 'is_sync', 'is_primary']
|
||||
self.default_columns = ['name', 'isSync', 'isMaster']
|
||||
|
||||
# hack
|
||||
def load_state(self, render_context=None):
|
||||
|
@ -73,6 +73,5 @@ class FakeQuerySet(EmptyQuerySet):
|
||||
class Node(models.Model):
|
||||
id = models.IntegerField(primary_key=True)
|
||||
name = models.CharField(max_length=20)
|
||||
is_primary = models.BooleanField(default=False)
|
||||
is_sync = models.BooleanField(default=False)
|
||||
is_async = models.BooleanField(default=False)
|
||||
isMaster = models.BooleanField(default=False)
|
||||
isSync = models.BooleanField(default=False)
|
||||
|
@ -21,6 +21,7 @@ from muranoclient.common.exceptions import HTTPForbidden, HTTPNotFound
|
||||
from openstack_dashboard.api.base import url_for
|
||||
from muranoclient.v1.client import Client
|
||||
from muranodashboard.panel.services import get_service_name
|
||||
from consts import STATUS_ID_READY, STATUS_ID_NEW
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -57,7 +58,7 @@ def get_status_messages_for_service(request, service_id, environment_id):
|
||||
result = '\n'
|
||||
#TODO: Add updated time to logs
|
||||
if deployments:
|
||||
for deployment in deployments:
|
||||
for deployment in reversed(deployments):
|
||||
reports = muranoclient(request).deployments.reports(environment_id,
|
||||
deployment.id,
|
||||
service_id)
|
||||
@ -156,8 +157,9 @@ def environments_list(request):
|
||||
if service:
|
||||
environments[index].has_services = True
|
||||
break
|
||||
if environments[index].status == u'ready':
|
||||
environments[index].status = u'new'
|
||||
if not environments[index].has_services:
|
||||
if environments[index].status == STATUS_ID_READY:
|
||||
environments[index].status = STATUS_ID_NEW
|
||||
return environments
|
||||
|
||||
|
||||
@ -207,6 +209,7 @@ def get_environment_name(request, environment_id):
|
||||
def get_environment_data(request, environment_id, *args):
|
||||
"""
|
||||
For given list of environment attributes return a values
|
||||
:return list
|
||||
"""
|
||||
|
||||
session_id = Session.get(request, environment_id)
|
||||
@ -234,7 +237,7 @@ def services_list(request, environment_id):
|
||||
for service_item in environment.services:
|
||||
service_data = service_item
|
||||
service_data['full_service_name'] = get_service_name(
|
||||
service_data['slug'])
|
||||
service_data['type'])
|
||||
|
||||
if service_data['id'] in reports and reports[service_data['id']]:
|
||||
last_operation = str(reports[service_data['id']].text)
|
||||
@ -324,6 +327,6 @@ def get_deployment_descr(request, environment_id, deployment_id):
|
||||
if 'services' in descr:
|
||||
for service in descr['services']:
|
||||
service['full_service_name'] = get_service_name(
|
||||
service['slug'])
|
||||
service['type'])
|
||||
return descr
|
||||
return None
|
||||
|
@ -20,16 +20,6 @@ from muranodashboard.panel.services import iterate_over_service_forms, \
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# has to be returned to all forms
|
||||
# def validate_hostname_template(template, instance_count):
|
||||
# if template and instance_count > 1:
|
||||
# if not '#' in template:
|
||||
# raise forms.ValidationError(
|
||||
# _('Incrementation symbol "#" is '
|
||||
# 'required in the Hostname template'))
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
class WizardFormServiceType(forms.Form):
|
||||
service = forms.ChoiceField(label=_('Service Type'),
|
||||
|
@ -1,115 +0,0 @@
|
||||
name: Active Directory
|
||||
type: activeDirectory
|
||||
|
||||
description: >-
|
||||
<strong> The Active Directory Service </strong>
|
||||
includes one primary and optionally a few secondary
|
||||
Domain Controllers, with DNS
|
||||
|
||||
unitTemplates:
|
||||
- isMaster: true
|
||||
recoveryPassword: $recoveryPassword
|
||||
location: west-dc
|
||||
- isMaster: false
|
||||
recoveryPassword: $recoveryPassword
|
||||
|
||||
forms:
|
||||
- - name: configuration
|
||||
type: string
|
||||
hidden: true
|
||||
initial: standalone
|
||||
- name: name
|
||||
type: string
|
||||
label: Domain Name
|
||||
description: >-
|
||||
Enter a desired name for a new domain. This name should fit
|
||||
in standard Windows domain name requirements: it should contain
|
||||
only A-Z, a-z, 0-9, and (-) and should not end with a dash.
|
||||
DNS server will be automatically set up on each of the Domain
|
||||
Controller instances.
|
||||
attributeNames: [name, domain]
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^([a-zA-Z\d][a-zA-Z\d-]*[a-zA-Z\d]\.){1,}[a-zA-Z\d][a-zA-Z\d-]*[a-zA-Z\d]$'
|
||||
errorMessages:
|
||||
invalid: >-
|
||||
Only letters, numbers and dashes in the middle are
|
||||
allowed. Period characters are allowed only when they are
|
||||
used to delimit the components of domain style
|
||||
names. Single-level domain is not appropriate.
|
||||
helpText: >-
|
||||
Just letters, numbers and dashes are allowed.
|
||||
A dot can be used to create subdomains
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
label: Instance Count
|
||||
description: >-
|
||||
You can create several Active Directory instances by setting
|
||||
instance number larger than one. One primary Domain Controller
|
||||
and a few secondary DCs will be created.
|
||||
attributeNames: units
|
||||
minValue: 1
|
||||
maxValue: 100
|
||||
initial: 1
|
||||
helpText: Enter an integer value between 1 and 100
|
||||
- name: adminAccountName
|
||||
type: string
|
||||
label: Account Name
|
||||
initial: Administrator
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: 'Just letters, numbers, underscores and hyphens are allowed.'
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
"Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 8 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different."
|
||||
- name: recoveryPassword
|
||||
type: password
|
||||
label: Recovery password
|
||||
attributeNames: false
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
"For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions."
|
||||
required: false
|
||||
#regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
required: false
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -1,92 +0,0 @@
|
||||
name: Internet Information Services
|
||||
type: webServer
|
||||
|
||||
description: >-
|
||||
<strong> The Internet Information Service </strong>
|
||||
sets up an IIS server and joins it into an existing domain
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: Standalone IIS Server
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
hidden: true
|
||||
attributeNames: units
|
||||
initial: 1
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
"Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 8 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different."
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
"For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions."
|
||||
required: false
|
||||
#regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
required: false
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -1,101 +0,0 @@
|
||||
name: ASP.NET Application
|
||||
type: aspNetApp
|
||||
|
||||
description: >-
|
||||
<strong> The ASP.NET Application Service </strong> installs
|
||||
custom application onto one IIS Web Server
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: ASP.NET application will be installed onto one IISWeb Server
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
hidden: true
|
||||
attributeNames: units
|
||||
initial: 1
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
"Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 8 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different."
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: repository
|
||||
type: string
|
||||
label: Git repository
|
||||
description: >-
|
||||
URL of a git repository with the application you want to deploy.
|
||||
regexpValidator: '/(\w+://)(.+@)*([\w\d\.]+)(:[\d]+)?/*(.*)/i'
|
||||
errorMessages:
|
||||
invalid: Enter correct git repository url
|
||||
helpText: Enter a valid git repository URL
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
"For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions."
|
||||
required: false
|
||||
#regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
required: false
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -1,109 +0,0 @@
|
||||
name: Internet Information Services Web Farm
|
||||
type: webServerFarm
|
||||
|
||||
description: >-
|
||||
<strong> The IIS Farm Service </strong> sets up a load-balanced set of IIS servers
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- - name: title
|
||||
type: string
|
||||
hidden: true
|
||||
required: false
|
||||
attributeNames: false
|
||||
description: A load-balanced array of IIS servers
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: username
|
||||
type: string
|
||||
hidden: true
|
||||
initial: Administrator
|
||||
attributeNames: credentials.username
|
||||
- name: adminPassword
|
||||
type: password
|
||||
attributeNames: [adminPassword, credentials.password]
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
"Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 8 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different."
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
minValue: 1
|
||||
maxValue: 100
|
||||
attributeNames: [units, instanceCount]
|
||||
initial: 1
|
||||
label: Instance Count
|
||||
description: Several instances with IIS Service can be created at one time.
|
||||
helpText: Enter an integer value between 1 and 100
|
||||
- name: loadBalancerPort
|
||||
type: integer
|
||||
label: Load Balancer port
|
||||
minValue: 1
|
||||
maxValue: 65536
|
||||
initial: 80
|
||||
description: Specify port number where Load Balancer will be running
|
||||
helpText: Enter an integer value from 1 to 65536
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
"For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions."
|
||||
required: false
|
||||
#regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
required: false
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -1,117 +0,0 @@
|
||||
name: ASP.NET Application Web Farm
|
||||
type: aspNetAppFarm
|
||||
|
||||
description: >-
|
||||
<strong> The ASP.NET Farm Service </strong> installs a custom application
|
||||
on a load-balanced array of IIS servers
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: >-
|
||||
The ASP.NET application will be installed on a number of IIS Web
|
||||
Servers, and load balancing will be configured.
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
hidden: true
|
||||
attributeNames: units
|
||||
initial: 1
|
||||
- name: username
|
||||
type: string
|
||||
hidden: true
|
||||
initial: Administrator
|
||||
attributeNames: credentials.username
|
||||
- name: adminPassword
|
||||
type: password
|
||||
attributeNames: [adminPassword, credentials.password]
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
"Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 8 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different."
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: repository
|
||||
type: string
|
||||
label: Git repository
|
||||
description: >-
|
||||
URL of a git repository with the application you want to deploy.
|
||||
regexpValidator: '/(\w+://)(.+@)*([\w\d\.]+)(:[\d]+)?/*(.*)/i'
|
||||
errorMessages:
|
||||
invalid: Enter correct git repository url
|
||||
helpText: Enter a valid git repository URL
|
||||
- name: loadBalancerPort
|
||||
type: integer
|
||||
label: Load Balancer port
|
||||
minValue: 1
|
||||
maxValue: 65536
|
||||
initial: 80
|
||||
description: Specify port number where Load Balancer will be running
|
||||
helpText: Enter an integer value from 1 to 65536
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
"For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions."
|
||||
required: false
|
||||
#regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
required: false
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -1,111 +0,0 @@
|
||||
name: MS SQL Server
|
||||
type: msSqlServer
|
||||
|
||||
description: >-
|
||||
<strong> The MS SQL Service </strong> installs an instance of
|
||||
Microsoft SQL Server
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: MS SQL Server
|
||||
# temporaryHack
|
||||
widgetMedia:
|
||||
js: [muranodashboard/js/mixed-mode.js]
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
hidden: true
|
||||
attributeNames: units
|
||||
initial: 1
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
"Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 8 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different."
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: mixedModeAuth
|
||||
type: boolean
|
||||
label: Mixed-mode Authentication
|
||||
initial: true
|
||||
required: false
|
||||
description: >-
|
||||
Mixed authentication mode allows the use of Windows
|
||||
credentials but supplements them with local SQL Server user
|
||||
accounts that the administrator may create and maintain within
|
||||
SQL Server. If this mode is on SA password is required
|
||||
- name: saPassword
|
||||
type: password
|
||||
label: SA Password
|
||||
description: Set system administrator password for the MS SQL Server.
|
||||
helpText: SQL server System Administrator account
|
||||
required: $mixedModeAuth
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
"For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions."
|
||||
required: false
|
||||
#regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
required: false
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -1,193 +0,0 @@
|
||||
name: MS SQL Server Cluster
|
||||
type: msSqlClusterServer
|
||||
|
||||
description: >-
|
||||
<strong> The MS SQL Failover Cluster </strong> installs
|
||||
Microsoft SQL Failover Cluster Server
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: MS SQL Failover Cluster
|
||||
# temporaryHack
|
||||
widgetMedia:
|
||||
js: [muranodashboard/js/mixed-mode.js, muranodashboard/js/external-ad.js]
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
"Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 8 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different."
|
||||
- name: externalAD
|
||||
type: boolean
|
||||
label: Active Directory is configured by the System Administrator
|
||||
widgetAttrs: # temporary hack
|
||||
class: external-ad
|
||||
required: false
|
||||
- name: domainAdminUserName
|
||||
type: string
|
||||
label: Active Directory User
|
||||
required: $externalAD
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: 'Just letters, numbers, underscores and hyphens are allowed.'
|
||||
- name: domainAdminPassword
|
||||
type: password
|
||||
label: Active Directory Password
|
||||
required: $externalAD
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: mixedModeAuth
|
||||
type: boolean
|
||||
label: Mixed-mode Authentication
|
||||
initial: true
|
||||
required: false
|
||||
description: >-
|
||||
Mixed authentication mode allows the use of Windows
|
||||
credentials but supplements them with local SQL Server user
|
||||
accounts that the administrator may create and maintain within
|
||||
SQL Server. If this mode is on SA password is required
|
||||
- name: saPassword
|
||||
type: password
|
||||
label: SA Password
|
||||
description: Set system administrator password for the MS SQL Server.
|
||||
helpText: SQL server System Administrator account
|
||||
required: $mixedModeAuth
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
"For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions."
|
||||
required: false
|
||||
#regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- - name: clusterIP
|
||||
type: clusterip
|
||||
label: Cluster Static IP
|
||||
description: Specify a valid IPv4 fixed IP.
|
||||
- name: clusterName
|
||||
type: string
|
||||
label: Cluster Name
|
||||
helpText: Service name for new SQL Cluster service
|
||||
description: >-
|
||||
Specify a name of a cluster. Just A-Z, a-z, 0-9, dash and underline are allowed.
|
||||
- name: agGroupName
|
||||
type: string
|
||||
label: Availability Group Name
|
||||
helpText: Name of AG during SQL setup
|
||||
description: >-
|
||||
Specify a name of an AG. Just A-Z, a-z, 0-9, dash and underline are allowed.
|
||||
- name: agListenerName
|
||||
type: string
|
||||
label: Availability Group Listener Name
|
||||
helpText: FQDN name of a new DNS entry for AG Listener endpoint
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
description: >-
|
||||
Specify a name of an AG Listener . Just A-Z, a-z, 0-9, dash and underline are allowed.
|
||||
- name: agListenerIP
|
||||
type: clusterip
|
||||
label: Availability Group Listener IP
|
||||
description: Specify a valid IPv4 fixed IP.
|
||||
- name: sqlServiceUserName
|
||||
type: string
|
||||
label: SQL User Name
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
description: User name that will be created to manage cluster instances.
|
||||
- name: sqlServicePassword
|
||||
type: password
|
||||
label: SQL User Password
|
||||
description: User password that will be created to manage cluster instances.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
label: Instance Count
|
||||
minValue: 2
|
||||
maxValue: 5
|
||||
initial: 2
|
||||
attributeNames: units
|
||||
helpText: Enter an integer value between 2 and 5
|
||||
description: Microsoft SQL Failover Cluster includes up to 5 instances.
|
||||
- - name: nodes
|
||||
type: datagrid
|
||||
label: Nodes
|
||||
description: >-
|
||||
Configure cluster instances. Cluster node quantity can be set
|
||||
with 'Add' and 'Remove' buttons. Configure Sync mode by
|
||||
enabling corresponding checkbox. All other nodes will be in
|
||||
Async mode. Just 2 nodes are allowed to be Sync. Also one
|
||||
Master node need to be selected. SQL Failover cluster has
|
||||
limit of 5 instances.
|
||||
- name: databases
|
||||
type: databaselist
|
||||
label: Database list
|
||||
description: >-
|
||||
Specify names for new databases which will be created as part
|
||||
of service installation. Here should come comma-separated list
|
||||
of database names, where each name has the following syntax:
|
||||
first symbol should be latin letter or underscore; subsequent
|
||||
symbols can be latin letter, numeric, underscore, at sign,
|
||||
number sign or dollar sign.
|
||||
helpText: Enter comma separated list of databases that will be created
|
||||
- - name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
required: false
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -11,93 +11,123 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import os
|
||||
from django.template.defaultfilters import slugify
|
||||
from ordereddict import OrderedDict
|
||||
from yaml.scanner import ScannerError
|
||||
import yaml
|
||||
import re
|
||||
|
||||
import os
|
||||
import re
|
||||
from django.conf import settings
|
||||
from ordereddict import OrderedDict
|
||||
import yaml
|
||||
from yaml.scanner import ScannerError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
_all_services = OrderedDict()
|
||||
|
||||
|
||||
class Service(object):
|
||||
def __init__(self, modified_on, **kwargs):
|
||||
import muranodashboard.panel.services.forms as services
|
||||
for key, value in kwargs.iteritems():
|
||||
if key == 'forms':
|
||||
self.forms = []
|
||||
for form_data in value:
|
||||
form_name, form_data = self.extract_form_data(form_data)
|
||||
self.forms.append(
|
||||
type(form_name, (services.ServiceConfigurationForm,),
|
||||
{'service': self,
|
||||
'fields_template': form_data['fields'],
|
||||
'validators': form_data.get('validators', [])}))
|
||||
else:
|
||||
setattr(self, key, value)
|
||||
self.modified_on = modified_on
|
||||
self.cleaned_data = {}
|
||||
|
||||
@staticmethod
|
||||
def extract_form_data(form_data):
|
||||
form_name = form_data.keys()[0]
|
||||
return form_name, form_data[form_name]
|
||||
|
||||
def update_cleaned_data(self, form, data):
|
||||
if data:
|
||||
# match = re.match('^.*-(\d)+$', form.prefix)
|
||||
# index = int(match.group(1)) if match else None
|
||||
# if index is not None:
|
||||
# self.cleaned_data[index] = data
|
||||
self.cleaned_data[form.__class__.__name__] = data
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
def import_all_services():
|
||||
import muranodashboard.panel.services.helpers as utils
|
||||
directory = os.path.dirname(__file__)
|
||||
for fname in sorted(os.listdir(directory)):
|
||||
from muranodashboard.panel.services.helpers import decamelize
|
||||
|
||||
directory = getattr(settings, 'MURANO_SERVICES_DESC_PATH', None)
|
||||
if directory is None:
|
||||
directory = os.path.join(os.path.dirname(__file__), '../../services/')
|
||||
|
||||
for filename in os.listdir(directory):
|
||||
if not filename.endswith('.yaml'):
|
||||
continue
|
||||
|
||||
service_file = os.path.join(directory, filename)
|
||||
modified_on = os.path.getmtime(service_file)
|
||||
|
||||
if filename in _all_services:
|
||||
if _all_services[filename].modified_on >= modified_on:
|
||||
continue
|
||||
|
||||
try:
|
||||
if fname.endswith('.yaml'):
|
||||
name = os.path.splitext(fname)[0]
|
||||
path = os.path.join(directory, fname)
|
||||
modified_on = os.stat(path).st_mtime
|
||||
if (not name in _all_services or
|
||||
_all_services[name][0] < modified_on):
|
||||
with open(path) as f:
|
||||
kwargs = dict(
|
||||
(utils.decamelize(k), v)
|
||||
for (k, v) in yaml.load(f).iteritems())
|
||||
_all_services[name] = (modified_on,
|
||||
type(name, (), kwargs))
|
||||
except ScannerError:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
with open(service_file) as stream:
|
||||
yaml_desc = yaml.load(stream)
|
||||
except (OSError, ScannerError):
|
||||
continue
|
||||
|
||||
service = dict((decamelize(k), v) for (k, v) in yaml_desc.iteritems())
|
||||
_all_services[filename] = Service(modified_on, **service)
|
||||
|
||||
|
||||
def iterate_over_services():
|
||||
import muranodashboard.panel.services.forms as services
|
||||
import_all_services()
|
||||
for id, service_data in _all_services.items():
|
||||
modified_on, service_cls = service_data
|
||||
forms = []
|
||||
for fields in service_cls.forms:
|
||||
class Form(services.ServiceConfigurationForm):
|
||||
service = service_cls
|
||||
fields_template = fields
|
||||
forms.append(Form)
|
||||
yield slugify(service_cls.name), service_cls, forms
|
||||
|
||||
for service in sorted(_all_services.values(), key=lambda v: v.name):
|
||||
yield service.type, service, service.forms
|
||||
|
||||
|
||||
def iterate_over_service_forms():
|
||||
for slug, Service, forms in iterate_over_services():
|
||||
for step, form in zip(xrange(len(forms)), forms):
|
||||
yield '{0}-{1}'.format(slug, step), form
|
||||
for srv_type, service, forms in iterate_over_services():
|
||||
for step, form in enumerate(forms):
|
||||
yield '{0}-{1}'.format(srv_type, step), form
|
||||
|
||||
|
||||
def with_service(slug, getter, default):
|
||||
import_all_services()
|
||||
match = re.match('(.*)-[0-9]+', slug)
|
||||
def service_type_from_id(service_id):
|
||||
match = re.match('(.*)-[0-9]+', service_id)
|
||||
if match:
|
||||
slug = match.group(1)
|
||||
for _slug, Service, forms in iterate_over_services():
|
||||
if _slug == slug:
|
||||
return getter(Service)
|
||||
return match.group(1)
|
||||
else: # if no number suffix found, it was service_type itself passed in
|
||||
return service_id
|
||||
|
||||
|
||||
def with_service(service_id, getter, default):
|
||||
import_all_services()
|
||||
service_type = service_type_from_id(service_id)
|
||||
for srv_type, service, forms in iterate_over_services():
|
||||
if srv_type == service_type:
|
||||
return getter(service)
|
||||
return default
|
||||
|
||||
|
||||
def get_service_template(slug):
|
||||
return with_service(slug, lambda Service: Service.template, '')
|
||||
def get_service_name(service_id):
|
||||
return with_service(service_id, lambda service: service.name, '')
|
||||
|
||||
|
||||
def get_service_name(slug):
|
||||
return with_service(slug, lambda Service: Service.name, '')
|
||||
|
||||
|
||||
def get_service_client(slug):
|
||||
return with_service(slug, lambda Service: Service.type, None)
|
||||
|
||||
|
||||
def get_service_field_descriptions(slug, index):
|
||||
def get_descriptions(Service):
|
||||
form = Service.forms[index]
|
||||
def get_service_field_descriptions(service_id, index):
|
||||
def get_descriptions(service):
|
||||
Form = service.forms[index]
|
||||
descriptions = []
|
||||
for field in form:
|
||||
for field in Form.fields_template:
|
||||
if 'description' in field:
|
||||
title = field.get('descriptionTitle', field.get('label', ''))
|
||||
descriptions.append((title, field['description']))
|
||||
return descriptions
|
||||
return with_service(slug, get_descriptions, [])
|
||||
return with_service(service_id, get_descriptions, [])
|
||||
|
||||
|
||||
def get_service_type(wizard):
|
||||
@ -107,23 +137,27 @@ def get_service_type(wizard):
|
||||
|
||||
|
||||
def get_service_choices():
|
||||
return [(slug, Service.name) for slug, Service, forms in
|
||||
return [(srv_type, service.name) for srv_type, service, forms in
|
||||
iterate_over_services()]
|
||||
|
||||
|
||||
def get_service_checkers():
|
||||
import_all_services()
|
||||
|
||||
def make_comparator(slug):
|
||||
def make_comparator(srv_id):
|
||||
def compare(wizard):
|
||||
match = re.match('(.*)-[0-9]+', slug)
|
||||
return match and match.group(1) == get_service_type(wizard)
|
||||
return service_type_from_id(srv_id) == get_service_type(wizard)
|
||||
return compare
|
||||
|
||||
return [(slug, make_comparator(slug)) for slug, form
|
||||
return [(srv_id, make_comparator(srv_id)) for srv_id, form
|
||||
in iterate_over_service_forms()]
|
||||
|
||||
|
||||
def get_service_descriptions():
|
||||
return [(slug, Service.description) for slug, Service, forms in
|
||||
iterate_over_services()]
|
||||
descriptions = []
|
||||
for srv_type, service, forms in iterate_over_services():
|
||||
description = getattr(service, 'description', _("<b>Default service \
|
||||
description</b>. If you want to see here something meaningful, please \
|
||||
provide `description' field in service markup."))
|
||||
descriptions.append((srv_type, description))
|
||||
return descriptions
|
||||
|
@ -13,7 +13,6 @@
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
import ast
|
||||
import json
|
||||
from django import forms
|
||||
from django.core.validators import RegexValidator, validate_ipv4_address
|
||||
@ -30,16 +29,35 @@ import copy
|
||||
|
||||
|
||||
def with_request(func):
|
||||
def update(self, initial):
|
||||
def update(self, initial, **kwargs):
|
||||
request = initial.get('request')
|
||||
if request:
|
||||
func(self, request, initial)
|
||||
func(self, request, **kwargs)
|
||||
else:
|
||||
raise forms.ValidationError("Can't get a request information")
|
||||
return update
|
||||
|
||||
|
||||
class PasswordField(forms.CharField):
|
||||
class CustomPropertiesField(object):
|
||||
@classmethod
|
||||
def push_properties(cls, kwargs):
|
||||
props = {}
|
||||
for key, value in kwargs.iteritems():
|
||||
if isinstance(value, property):
|
||||
props[key] = value
|
||||
for key in props.keys():
|
||||
del kwargs[key]
|
||||
if props:
|
||||
return type('cls_with_props', (cls,), props)
|
||||
else:
|
||||
return cls
|
||||
|
||||
|
||||
class CharField(forms.CharField, CustomPropertiesField):
|
||||
pass
|
||||
|
||||
|
||||
class PasswordField(CharField):
|
||||
special_characters = '!@#$%^&*()_+|\/.,~?><:{}'
|
||||
password_re = re.compile('^.*(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[%s]).*$'
|
||||
% special_characters)
|
||||
@ -53,7 +71,9 @@ class PasswordField(forms.CharField):
|
||||
return name + '-clone'
|
||||
|
||||
def compare(self, name, form_data):
|
||||
if self.is_original(): # run compare only for original fields
|
||||
if self.is_original() and self.required:
|
||||
# run compare only for original fields
|
||||
# do not run compare for hidden fields (they are not required)
|
||||
if form_data.get(name) != form_data.get(self.get_clone_name(name)):
|
||||
raise forms.ValidationError(_(u"{0}{1} don't match".format(
|
||||
self.label, pluralize(2))))
|
||||
@ -84,6 +104,11 @@ class PasswordField(forms.CharField):
|
||||
help_text=help_text,
|
||||
widget=self.PasswordInput(render_value=True))
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
result = super(PasswordField, self).__deepcopy__(memo)
|
||||
result.error_messages = copy.deepcopy(self.error_messages)
|
||||
return result
|
||||
|
||||
def is_original(self):
|
||||
return hasattr(self, 'original') and self.original
|
||||
|
||||
@ -97,23 +122,41 @@ class PasswordField(forms.CharField):
|
||||
return field
|
||||
|
||||
|
||||
class InstanceCountField(forms.IntegerField):
|
||||
class IntegerField(forms.IntegerField, CustomPropertiesField):
|
||||
pass
|
||||
|
||||
|
||||
class InstanceCountField(IntegerField):
|
||||
def clean(self, value):
|
||||
self.value = super(InstanceCountField, self).clean(value)
|
||||
return self.value
|
||||
|
||||
def postclean(self, form, data):
|
||||
value = []
|
||||
for dc in range(self.value):
|
||||
if hasattr(self, 'value'):
|
||||
templates = form.get_unit_templates(data)
|
||||
if dc < len(templates) - 1:
|
||||
value.append(templates[dc])
|
||||
for dc in range(self.value):
|
||||
if dc < len(templates) - 1:
|
||||
template = templates[dc]
|
||||
else:
|
||||
template = templates[-1]
|
||||
value.append(self.interpolate_number(template, dc + 1))
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def interpolate_number(spec, number):
|
||||
"""Replaces all '#' occurrences with given number."""
|
||||
def interpolate(spec):
|
||||
if type(spec) == dict:
|
||||
return dict((k, interpolate(v)) for (k, v) in spec.iteritems())
|
||||
elif type(spec) in (str, unicode) and '#' in spec:
|
||||
return spec.replace('#', '{0}').format(number)
|
||||
else:
|
||||
value.append(templates[-1])
|
||||
return value
|
||||
return spec
|
||||
return interpolate(spec)
|
||||
|
||||
|
||||
class DataGridField(forms.MultiValueField):
|
||||
class DataGridField(forms.MultiValueField, CustomPropertiesField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['widget'] = DataGridCompound
|
||||
super(DataGridField, self).__init__(
|
||||
@ -124,21 +167,22 @@ class DataGridField(forms.MultiValueField):
|
||||
return data_list[1]
|
||||
|
||||
@with_request
|
||||
def update(self, request, initial):
|
||||
def update(self, request, **kwargs):
|
||||
self.widget.update_request(request)
|
||||
nodes = []
|
||||
instance_count = initial.get('instance_count')
|
||||
if instance_count:
|
||||
for index in xrange(instance_count):
|
||||
nodes.append({'name': 'node' + str(index + 1),
|
||||
'is_sync': index < 2,
|
||||
'is_primary': index == 0})
|
||||
self.initial = json.dumps(nodes)
|
||||
# hack to use json string instead of python dict get by YAQL
|
||||
data = kwargs['form'].service.cleaned_data
|
||||
if 'clusterConfiguration' in data:
|
||||
conf = data['clusterConfiguration']
|
||||
conf['dcInstances'] = json.dumps(conf['dcInstances'])
|
||||
|
||||
|
||||
class DomainChoiceField(forms.ChoiceField):
|
||||
class ChoiceField(forms.ChoiceField, CustomPropertiesField):
|
||||
pass
|
||||
|
||||
|
||||
class DomainChoiceField(ChoiceField):
|
||||
@with_request
|
||||
def update(self, request, initial):
|
||||
def update(self, request, **kwargs):
|
||||
self.choices = [("", "Not in domain")]
|
||||
link = request.__dict__['META']['HTTP_REFERER']
|
||||
environment_id = re.search(
|
||||
@ -149,9 +193,9 @@ class DomainChoiceField(forms.ChoiceField):
|
||||
[(domain.name, domain.name) for domain in domains])
|
||||
|
||||
|
||||
class FlavorChoiceField(forms.ChoiceField):
|
||||
class FlavorChoiceField(ChoiceField):
|
||||
@with_request
|
||||
def update(self, request, initial):
|
||||
def update(self, request, **kwargs):
|
||||
self.choices = [(flavor.name, flavor.name) for flavor in
|
||||
novaclient(request).flavors.list()]
|
||||
for flavor in self.choices:
|
||||
@ -160,33 +204,28 @@ class FlavorChoiceField(forms.ChoiceField):
|
||||
break
|
||||
|
||||
|
||||
class ImageChoiceField(forms.ChoiceField):
|
||||
class ImageChoiceField(ChoiceField):
|
||||
@with_request
|
||||
def update(self, request, initial):
|
||||
def update(self, request, **kwargs):
|
||||
try:
|
||||
# public filter removed
|
||||
images, _more = glance.image_list_detailed(request)
|
||||
except:
|
||||
images = []
|
||||
exceptions.handle(request,
|
||||
_("Unable to retrieve public images."))
|
||||
exceptions.handle(request, _("Unable to retrieve public images."))
|
||||
|
||||
image_mapping, image_choices = {}, []
|
||||
for image in images:
|
||||
murano_property = image.properties.get('murano_image_info')
|
||||
if murano_property:
|
||||
# convert to dict because
|
||||
# only string can be stored in image metadata property
|
||||
try:
|
||||
murano_json = ast.literal_eval(murano_property)
|
||||
murano_json = json.loads(murano_property)
|
||||
except ValueError:
|
||||
messages.error(request,
|
||||
_("Invalid value in image metadata"))
|
||||
messages.error(request, _("Invalid murano image metadata"))
|
||||
else:
|
||||
title = murano_json.get('title')
|
||||
image_id = murano_json.get('id')
|
||||
if title and image_id:
|
||||
image_mapping[smart_text(title)] = smart_text(image_id)
|
||||
title = murano_json.get('title', image.name)
|
||||
murano_json['name'] = image.name
|
||||
image_mapping[smart_text(title)] = json.dumps(murano_json)
|
||||
|
||||
for name in sorted(image_mapping.keys()):
|
||||
image_choices.append((image_mapping[name], name))
|
||||
@ -197,10 +236,14 @@ class ImageChoiceField(forms.ChoiceField):
|
||||
|
||||
self.choices = image_choices
|
||||
|
||||
def clean(self, value):
|
||||
value = super(ImageChoiceField, self).clean(value)
|
||||
return json.loads(value) if value else value
|
||||
|
||||
class AZoneChoiceField(forms.ChoiceField):
|
||||
|
||||
class AZoneChoiceField(ChoiceField):
|
||||
@with_request
|
||||
def update(self, request, initial):
|
||||
def update(self, request, **kwargs):
|
||||
try:
|
||||
availability_zones = novaclient(request).availability_zones.\
|
||||
list(detailed=False)
|
||||
@ -211,21 +254,19 @@ class AZoneChoiceField(forms.ChoiceField):
|
||||
|
||||
az_choices = [(az.zoneName, az.zoneName)
|
||||
for az in availability_zones if az.zoneState]
|
||||
if az_choices:
|
||||
az_choices.insert(0, ("", _("Select Availability Zone")))
|
||||
else:
|
||||
if not az_choices:
|
||||
az_choices.insert(0, ("", _("No availability zones available")))
|
||||
|
||||
self.choices = az_choices
|
||||
|
||||
|
||||
class BooleanField(forms.BooleanField):
|
||||
class BooleanField(forms.BooleanField, CustomPropertiesField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['widget'] = forms.CheckboxInput(attrs={'class': 'checkbox'})
|
||||
super(BooleanField, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class ClusterIPField(forms.CharField):
|
||||
class ClusterIPField(CharField):
|
||||
@staticmethod
|
||||
def validate_cluster_ip(request, ip_ranges):
|
||||
def perform_checking(ip):
|
||||
@ -240,6 +281,10 @@ class ClusterIPField(forms.CharField):
|
||||
request, _("Unable to retrieve information "
|
||||
"about fixed IP or IP is not valid."),
|
||||
ignore=True)
|
||||
except exceptions.NOT_FOUND:
|
||||
exceptions.handle(
|
||||
request, _("Could not found fixed ips for ip %s" % (ip,)),
|
||||
ignore=True)
|
||||
else:
|
||||
if ip_info.hostname:
|
||||
raise forms.ValidationError(
|
||||
@ -247,7 +292,7 @@ class ClusterIPField(forms.CharField):
|
||||
return perform_checking
|
||||
|
||||
@with_request
|
||||
def update(self, request, initial):
|
||||
def update(self, request, **kwargs):
|
||||
try:
|
||||
network_list = novaclient(request).networks.list()
|
||||
ip_ranges = [network.cidr for network in network_list]
|
||||
@ -261,18 +306,8 @@ class ClusterIPField(forms.CharField):
|
||||
self.validators = [self.validate_cluster_ip(request, ip_ranges)]
|
||||
self.error_messages['invalid'] = validate_ipv4_address.message
|
||||
|
||||
def postclean(self, form, data):
|
||||
# hack to compare two IPs
|
||||
ips = []
|
||||
for key, field in form.fields.items():
|
||||
if isinstance(field, ClusterIPField):
|
||||
ips.append(data.get(key))
|
||||
if ips[0] == ips[1] and ips[0] is not None:
|
||||
raise forms.ValidationError(_(
|
||||
'Listener IP and Cluster Static IP should be different'))
|
||||
|
||||
|
||||
class DatabaseListField(forms.CharField):
|
||||
class DatabaseListField(CharField):
|
||||
validate_mssql_identifier = RegexValidator(
|
||||
re.compile(r'^[a-zA-z_][a-zA-Z0-9_$#@]*$'),
|
||||
_((u'First symbol should be latin letter or underscore. Subsequent ' +
|
||||
|
@ -18,6 +18,8 @@ from django.core.validators import RegexValidator
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import muranodashboard.panel.services.fields as fields
|
||||
import muranodashboard.panel.services.helpers as helpers
|
||||
import yaql
|
||||
import types
|
||||
|
||||
|
||||
class UpdatableFieldsForm(forms.Form):
|
||||
@ -39,12 +41,30 @@ class UpdatableFieldsForm(forms.Form):
|
||||
|
||||
for name, field in self.fields.iteritems():
|
||||
if hasattr(field, 'update'):
|
||||
field.update(self.initial)
|
||||
field.update(self.initial, form=self)
|
||||
if not field.required:
|
||||
field.widget.attrs['placeholder'] = 'Optional'
|
||||
|
||||
|
||||
class ServiceConfigurationForm(UpdatableFieldsForm):
|
||||
types = {
|
||||
'string': fields.CharField,
|
||||
'boolean': fields.BooleanField,
|
||||
'instance': fields.InstanceCountField,
|
||||
'clusterip': fields.ClusterIPField,
|
||||
'domain': fields.DomainChoiceField,
|
||||
'password': fields.PasswordField,
|
||||
'integer': fields.IntegerField,
|
||||
'databaselist': fields.DatabaseListField,
|
||||
'datagrid': fields.DataGridField,
|
||||
'flavor': fields.FlavorChoiceField,
|
||||
'image': fields.ImageChoiceField,
|
||||
'azone': fields.AZoneChoiceField,
|
||||
'text': (fields.CharField, forms.Textarea)
|
||||
}
|
||||
|
||||
localizable_keys = set(['label', 'help_text', 'error_messages'])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ServiceConfigurationForm, self).__init__(*args, **kwargs)
|
||||
self.attribute_mappings = {}
|
||||
@ -52,25 +72,9 @@ class ServiceConfigurationForm(UpdatableFieldsForm):
|
||||
self.initial = kwargs.get('initial', self.initial)
|
||||
self.update_fields()
|
||||
|
||||
EVAL_PREFIX = '$'
|
||||
|
||||
types = {
|
||||
'string': forms.CharField,
|
||||
'boolean': fields.BooleanField,
|
||||
'instance': fields.InstanceCountField,
|
||||
'clusterip': fields.ClusterIPField,
|
||||
'domain': fields.DomainChoiceField,
|
||||
'password': fields.PasswordField,
|
||||
'integer': forms.IntegerField,
|
||||
'databaselist': fields.DatabaseListField,
|
||||
'datagrid': fields.DataGridField,
|
||||
'flavor': fields.FlavorChoiceField,
|
||||
'image': fields.ImageChoiceField,
|
||||
'azone': fields.AZoneChoiceField,
|
||||
'text': (forms.CharField, forms.Textarea)
|
||||
}
|
||||
|
||||
localizable_keys = set(['label', 'help_text', 'error_messages'])
|
||||
@staticmethod
|
||||
def get_yaql_expr(expr):
|
||||
return type(expr) == dict and expr.get('YAQL', None)
|
||||
|
||||
def init_attribute_mappings(self, field_name, kwargs):
|
||||
def set_mapping(name, value):
|
||||
@ -123,18 +127,6 @@ class ServiceConfigurationForm(UpdatableFieldsForm):
|
||||
del kwargs['widget_attrs']
|
||||
return widget
|
||||
|
||||
def append_properties(cls, kwargs):
|
||||
props = {}
|
||||
for key, value in kwargs.iteritems():
|
||||
if isinstance(value, property):
|
||||
props[key] = value
|
||||
for key in props.keys():
|
||||
del kwargs[key]
|
||||
if props:
|
||||
return type('cls_with_props', (cls,), props)
|
||||
else:
|
||||
return cls
|
||||
|
||||
def append_field(field_spec):
|
||||
cls = parse_spec(field_spec['type'], 'type')[1]
|
||||
widget = None
|
||||
@ -142,7 +134,7 @@ class ServiceConfigurationForm(UpdatableFieldsForm):
|
||||
cls, widget = cls
|
||||
kwargs = parse_spec(field_spec)[1]
|
||||
kwargs['widget'] = process_widget(kwargs, cls, widget)
|
||||
cls = append_properties(cls, kwargs)
|
||||
cls = cls.push_properties(kwargs)
|
||||
|
||||
self.init_attribute_mappings(field_spec['name'], kwargs)
|
||||
self.init_field_descriptions(kwargs)
|
||||
@ -166,11 +158,25 @@ class ServiceConfigurationForm(UpdatableFieldsForm):
|
||||
def is_localizable(keys):
|
||||
return set(keys).intersection(self.localizable_keys)
|
||||
|
||||
def make_property(key, spec):
|
||||
def _get(field):
|
||||
data_ready, value = self.get_data(spec)
|
||||
return value if data_ready else field.__dict__[key]
|
||||
|
||||
def _set(field, value):
|
||||
field.__dict__[key] = value
|
||||
|
||||
def _del(field):
|
||||
del field.__dict__[key]
|
||||
return property(_get, _set, _del)
|
||||
|
||||
def parse_spec(spec, keys=[]):
|
||||
if not type(keys) == list:
|
||||
keys = [keys]
|
||||
key = keys and keys[-1] or None
|
||||
if type(spec) == dict:
|
||||
if self.get_yaql_expr(spec):
|
||||
return key, make_property(key, spec)
|
||||
elif type(spec) == dict:
|
||||
items = []
|
||||
for k, v in spec.iteritems():
|
||||
if not k in ('type', 'name'):
|
||||
@ -191,69 +197,67 @@ class ServiceConfigurationForm(UpdatableFieldsForm):
|
||||
return 'widget', forms.HiddenInput
|
||||
elif key == 'regexp_validator':
|
||||
return 'validators', [prepare_regexp(spec)]
|
||||
elif (type(spec) in (str, unicode) and
|
||||
spec[0] == self.EVAL_PREFIX):
|
||||
def _get(field):
|
||||
"""First try to get value from cleaned data, if none
|
||||
found, use raw data."""
|
||||
data = getattr(self, 'cleaned_data', None)
|
||||
value = data and data.get(spec[1:], None)
|
||||
if value is None:
|
||||
name = self.add_prefix(spec[1:])
|
||||
value = self.data.get(name, None)
|
||||
return value
|
||||
|
||||
def _set(field, value):
|
||||
# doesn't work - why?
|
||||
# super(field.__class__, field).__setattr__(key, value)
|
||||
field.__dict__[key] = value
|
||||
|
||||
def _del(field):
|
||||
# doesn't work - why?
|
||||
# super(field.__class__, field).__delattr__(key)
|
||||
del field.__dict__[key]
|
||||
|
||||
return key, property(_get, _set, _del)
|
||||
else:
|
||||
return key, spec
|
||||
|
||||
for spec in field_specs:
|
||||
append_field(spec)
|
||||
|
||||
def get_data(self, expr, data=None):
|
||||
"""First try to get value from cleaned data, if none
|
||||
found, use raw data."""
|
||||
context = yaql.create_context()
|
||||
data = self.service.update_cleaned_data(
|
||||
self, data or getattr(self, 'cleaned_data', None))
|
||||
expr = self.get_yaql_expr(expr)
|
||||
value = data and yaql.parse(expr).evaluate(data, context)
|
||||
return data != {}, value
|
||||
|
||||
def get_unit_templates(self, data):
|
||||
def parse_spec(spec):
|
||||
if type(spec) == list:
|
||||
if self.get_yaql_expr(spec):
|
||||
data_ready, value = self.get_data(spec, data)
|
||||
return value
|
||||
elif isinstance(spec, types.ListType):
|
||||
return [parse_spec(_spec) for _spec in spec]
|
||||
elif type(spec) == dict:
|
||||
elif isinstance(spec, types.DictType):
|
||||
return dict(
|
||||
(parse_spec(k), parse_spec(v))
|
||||
for (k, v) in spec.iteritems())
|
||||
elif (type(spec) in (str, unicode) and
|
||||
spec[0] == self.EVAL_PREFIX):
|
||||
return data.get(spec[1:])
|
||||
else:
|
||||
return spec
|
||||
return [parse_spec(spec) for spec in self.service.unit_templates]
|
||||
|
||||
def extract_attributes(self, attributes):
|
||||
def get_data(name):
|
||||
def get_attr(name):
|
||||
if type(name) == dict:
|
||||
return dict((k, get_data(v)) for (k, v) in name.iteritems())
|
||||
return dict((k, get_attr(v)) for (k, v) in name.iteritems())
|
||||
else:
|
||||
return self.cleaned_data[name]
|
||||
for attr_name, field_name in self.attribute_mappings.iteritems():
|
||||
attributes[attr_name] = get_data(field_name)
|
||||
attributes[attr_name] = get_attr(field_name)
|
||||
|
||||
def clean(self):
|
||||
form_data = self.cleaned_data
|
||||
if self._errors:
|
||||
return self.cleaned_data
|
||||
else:
|
||||
cleaned_data = super(ServiceConfigurationForm, self).clean()
|
||||
all_data = self.service.update_cleaned_data(self, cleaned_data)
|
||||
context = yaql.create_context()
|
||||
for validator in self.validators:
|
||||
expr = self.get_yaql_expr(validator['expr'])
|
||||
if not yaql.parse(expr).evaluate(all_data, context):
|
||||
raise forms.ValidationError(
|
||||
_(validator.get('message', '')))
|
||||
|
||||
for name, field in self.fields.iteritems():
|
||||
if isinstance(field, fields.PasswordField):
|
||||
field.compare(name, form_data)
|
||||
for name, field in self.fields.iteritems():
|
||||
if isinstance(field, fields.PasswordField):
|
||||
field.compare(name, cleaned_data)
|
||||
|
||||
if hasattr(field, 'postclean'):
|
||||
value = field.postclean(self, form_data)
|
||||
if value:
|
||||
self.cleaned_data[name] = value
|
||||
if hasattr(field, 'postclean'):
|
||||
value = field.postclean(self, cleaned_data)
|
||||
if value:
|
||||
cleaned_data[name] = value
|
||||
|
||||
return self.cleaned_data
|
||||
self.service.update_cleaned_data(self, cleaned_data)
|
||||
return cleaned_data
|
||||
|
@ -95,7 +95,7 @@ class DeleteService(tables.DeleteAction):
|
||||
|
||||
def allowed(self, request, service=None):
|
||||
environment_id = self.table.kwargs.get('environment_id')
|
||||
status = api.get_environment_data(request, environment_id, 'status')
|
||||
status, = api.get_environment_data(request, environment_id, 'status')
|
||||
|
||||
return False if status == STATUS_ID_DEPLOYING else True
|
||||
|
||||
@ -132,7 +132,7 @@ class DeployEnvironment(tables.BatchAction):
|
||||
def action(self, request, environment_id):
|
||||
try:
|
||||
api.environment_deploy(request, environment_id)
|
||||
except:
|
||||
except Exception:
|
||||
msg = _('Unable to deploy. Try again later')
|
||||
redirect = reverse('horizon:project:murano:index')
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
@ -39,7 +39,7 @@ from muranoclient.common.exceptions import HTTPUnauthorized, \
|
||||
CommunicationError, HTTPInternalServerError, HTTPForbidden, HTTPNotFound
|
||||
|
||||
from muranodashboard.panel.services import get_service_descriptions, \
|
||||
get_service_name, get_service_client, get_service_field_descriptions
|
||||
get_service_name, get_service_field_descriptions
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -54,20 +54,15 @@ class Wizard(ModalFormMixin, SessionWizardView):
|
||||
args=(environment_id,))
|
||||
|
||||
step0_data = form_list[0].cleaned_data
|
||||
slug = step0_data.get('service', '')
|
||||
attributes = {'type': get_service_client(slug),
|
||||
'slug': slug}
|
||||
service_type = step0_data.get('service', '')
|
||||
attributes = {'type': service_type}
|
||||
|
||||
for form in form_list[1:]:
|
||||
form.extract_attributes(attributes)
|
||||
|
||||
# hack to fill units with data from nodes datagrid
|
||||
# hack to destringify nodes into units
|
||||
if 'nodes' in attributes:
|
||||
units = []
|
||||
for node in json.loads(attributes['nodes']):
|
||||
units.append({'isMaster': node['is_primary'],
|
||||
'isSync': node['is_sync']})
|
||||
attributes['units'] = units
|
||||
attributes['units'] = json.loads(attributes['nodes'])
|
||||
del attributes['nodes']
|
||||
|
||||
try:
|
||||
@ -80,10 +75,11 @@ class Wizard(ModalFormMixin, SessionWizardView):
|
||||
except Exception:
|
||||
redirect = reverse("horizon:project:murano:index")
|
||||
exceptions.handle(self.request,
|
||||
_('Sorry, you can\'t create service right now.',
|
||||
redirect=redirect))
|
||||
_('Sorry, you can\'t create service right now.'),
|
||||
redirect=redirect)
|
||||
else:
|
||||
message = "The %s service successfully created." % slug
|
||||
message = "The %s service successfully created." % \
|
||||
get_service_name(service_type)
|
||||
messages.success(self.request, message)
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
@ -91,14 +87,6 @@ class Wizard(ModalFormMixin, SessionWizardView):
|
||||
init_dict = {}
|
||||
if step != 'service_choice':
|
||||
init_dict['request'] = self.request
|
||||
|
||||
# hack to pass number of nodes from one form to another
|
||||
if step == 'ms-sql-server-cluster-2':
|
||||
form_id = 'ms-sql-server-cluster-1'
|
||||
form_data = self.storage.data['step_data'].get(form_id, {})
|
||||
instance_count = form_data.get(form_id + '-dcInstances')
|
||||
if instance_count:
|
||||
init_dict['instance_count'] = int(instance_count[0])
|
||||
return self.initial_dict.get(step, init_dict)
|
||||
|
||||
def get_context_data(self, form, **kwargs):
|
||||
@ -106,11 +94,11 @@ class Wizard(ModalFormMixin, SessionWizardView):
|
||||
context['service_descriptions'] = get_service_descriptions()
|
||||
if self.steps.index > 0:
|
||||
data = self.get_cleaned_data_for_step('service_choice')
|
||||
slug = data['service']
|
||||
service_type = data['service']
|
||||
context['field_descriptions'] = get_service_field_descriptions(
|
||||
slug, self.steps.index - 1)
|
||||
context.update({'type': get_service_client(slug),
|
||||
'service_name': get_service_name(slug)})
|
||||
service_type, self.steps.index - 1)
|
||||
context.update({'type': service_type,
|
||||
'service_name': get_service_name(service_type)})
|
||||
return context
|
||||
|
||||
|
||||
|
122
muranodashboard/services/ActiveDirectory.yaml
Normal file
122
muranodashboard/services/ActiveDirectory.yaml
Normal file
@ -0,0 +1,122 @@
|
||||
name: Active Directory
|
||||
type: activeDirectory
|
||||
|
||||
description: >-
|
||||
<strong> The Active Directory Service </strong>
|
||||
includes one primary and optionally a few secondary
|
||||
Domain Controllers, with DNS
|
||||
|
||||
unitTemplates:
|
||||
- isMaster: true
|
||||
recoveryPassword: {YAQL: $.serviceConfiguration.recoveryPassword}
|
||||
- isMaster: false
|
||||
recoveryPassword: {YAQL: $.serviceConfiguration.recoveryPassword}
|
||||
|
||||
forms:
|
||||
- serviceConfiguration:
|
||||
fields:
|
||||
- name: configuration
|
||||
type: string
|
||||
hidden: true
|
||||
initial: standalone
|
||||
- name: name
|
||||
type: string
|
||||
label: Domain Name
|
||||
description: >-
|
||||
Enter a desired name for a new domain. This name should fit to
|
||||
DNS Domain Name requirements: it should contain
|
||||
only A-Z, a-z, 0-9, (.) and (-) and should not end with a dash.
|
||||
DNS server will be automatically set up on each of the Domain
|
||||
Controller instances. Note: Only first 15 characters or characters
|
||||
before first period is used as NetBIOS name.
|
||||
attributeNames: [name, domain]
|
||||
minLength: 2
|
||||
maxLength: 255
|
||||
regexpValidator: '^[0-9A-Za-z](?!--)[0-9A-Za-z\-]{0,13}[0-9A-Za-z]\.[0-9A-Za-z][0-9A-Za-z\-]{0,61}[0-9A-Za-z]$'
|
||||
errorMessages:
|
||||
invalid: >-
|
||||
Only letters, numbers and dashes in the middle are
|
||||
allowed. Period characters are allowed only when they are
|
||||
used to delimit the components of domain style
|
||||
names. Single-level domain is not appropriate.
|
||||
helpText: >-
|
||||
Just letters, numbers and dashes are allowed.
|
||||
A dot can be used to create subdomains
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
label: Instance Count
|
||||
description: >-
|
||||
You can create several Active Directory instances by setting
|
||||
instance number larger than one. One primary Domain Controller
|
||||
and a few secondary DCs will be created.
|
||||
attributeNames: units
|
||||
minValue: 1
|
||||
maxValue: 100
|
||||
initial: 1
|
||||
helpText: Enter an integer value between 1 and 100
|
||||
- name: adminAccountName
|
||||
type: string
|
||||
label: Account Name
|
||||
initial: Administrator
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: 'Just letters, numbers, underscores and hyphens are allowed.'
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 7 characters.
|
||||
|
||||
Once you forget your password you won't be able to
|
||||
operate the service until recovery password would be entered. So it's
|
||||
better for Recovery and Administrator password to be different.
|
||||
- name: recoveryPassword
|
||||
type: password
|
||||
label: Recovery password
|
||||
attributeNames: false
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions.
|
||||
required: false
|
||||
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
validators:
|
||||
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
|
||||
- expr: {YAQL: $.serviceConfiguration.dcInstances < 2 or not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
|
||||
message: Incrementation symbol "#" is required in the Hostname template
|
||||
- instanceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
100
muranodashboard/services/AspNetApp.yaml
Normal file
100
muranodashboard/services/AspNetApp.yaml
Normal file
@ -0,0 +1,100 @@
|
||||
name: ASP.NET Application
|
||||
type: aspNetApp
|
||||
|
||||
description: >-
|
||||
<strong> The ASP.NET Application Service </strong> installs
|
||||
custom application onto one IIS Web Server
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- serviceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: ASP.NET application will be installed onto one IISWeb Server
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
hidden: true
|
||||
attributeNames: units
|
||||
initial: 1
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 7 characters.
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: repository
|
||||
type: string
|
||||
label: Git repository
|
||||
description: >-
|
||||
URL of a git repository with the application you want to deploy.
|
||||
regexpValidator: '/(\w+://)(.+@)*([\w\d\.]+)(:[\d]+)?/*(.*)/i'
|
||||
errorMessages:
|
||||
invalid: Enter correct git repository url
|
||||
helpText: Enter a valid git repository URL
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions.
|
||||
required: false
|
||||
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- instanceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
125
muranodashboard/services/AspNetAppFarm.yaml
Normal file
125
muranodashboard/services/AspNetAppFarm.yaml
Normal file
@ -0,0 +1,125 @@
|
||||
name: ASP.NET Application Web Farm
|
||||
type: aspNetAppFarm
|
||||
|
||||
description: >-
|
||||
<strong> The ASP.NET Farm Service </strong> installs a custom application
|
||||
on a load-balanced array of IIS servers
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- serviceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: >-
|
||||
The ASP.NET application will be installed on a number of IIS Web
|
||||
Servers, and load balancing will be configured.
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: username
|
||||
type: string
|
||||
hidden: true
|
||||
initial: Administrator
|
||||
attributeNames: credentials.username
|
||||
- name: adminPassword
|
||||
type: password
|
||||
attributeNames: [adminPassword, credentials.password]
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 7 characters.
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: repository
|
||||
type: string
|
||||
label: Git repository
|
||||
description: >-
|
||||
URL of a git repository with the application you want to deploy.
|
||||
regexpValidator: '/(\w+://)(.+@)*([\w\d\.]+)(:[\d]+)?/*(.*)/i'
|
||||
errorMessages:
|
||||
invalid: Enter correct git repository url
|
||||
helpText: Enter a valid git repository URL
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
label: Instance Count
|
||||
description: >-
|
||||
Several instances with ASP.NET application can be created at one time.
|
||||
attributeNames: units
|
||||
minValue: 2
|
||||
maxValue: 100
|
||||
initial: 2
|
||||
helpText: Enter an integer value between 2 and 100
|
||||
- name: loadBalancerPort
|
||||
type: integer
|
||||
label: Load Balancer port
|
||||
minValue: 1
|
||||
maxValue: 65536
|
||||
initial: 80
|
||||
description: Specify port number where Load Balancer will be running
|
||||
helpText: Enter an integer value from 1 to 65536
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions.
|
||||
required: false
|
||||
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
validators:
|
||||
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
|
||||
- expr: {YAQL: not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
|
||||
message: Incrementation symbol "#" is required in the Hostname template
|
||||
- instanceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
214
muranodashboard/services/MsSqlClusterServer.yaml
Normal file
214
muranodashboard/services/MsSqlClusterServer.yaml
Normal file
@ -0,0 +1,214 @@
|
||||
name: MS SQL Server Cluster
|
||||
type: msSqlClusterServer
|
||||
|
||||
description: >-
|
||||
<strong> The MS SQL Failover Cluster </strong> installs
|
||||
Microsoft SQL Failover Cluster Server
|
||||
|
||||
unitTemplates:
|
||||
- isMaster: true
|
||||
isSync: true
|
||||
name: 'node#'
|
||||
- isMaster: false
|
||||
isSync: true
|
||||
name: 'node#'
|
||||
- isMaster: false
|
||||
isSync: false
|
||||
name: 'node#'
|
||||
|
||||
forms:
|
||||
- serviceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: MS SQL Failover Cluster
|
||||
# temporaryHack
|
||||
widgetMedia:
|
||||
js: [muranodashboard/js/mixed-mode.js, muranodashboard/js/external-ad.js]
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 7 characters.
|
||||
- name: externalAD
|
||||
type: boolean
|
||||
label: Active Directory is configured by the System Administrator
|
||||
widgetAttrs: # temporary hack
|
||||
class: external-ad
|
||||
required: false
|
||||
- name: domainAdminUserName
|
||||
type: string
|
||||
label: Active Directory User
|
||||
required: {YAQL: $.serviceConfiguration.externalAD}
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: 'Just letters, numbers, underscores and hyphens are allowed.'
|
||||
- name: domainAdminPassword
|
||||
type: password
|
||||
label: Active Directory Password
|
||||
required: {YAQL: $.serviceConfiguration.externalAD}
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: {YAQL: not $.serviceConfiguration.externalAD}
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: mixedModeAuth
|
||||
type: boolean
|
||||
label: Mixed-mode Authentication
|
||||
initial: true
|
||||
required: false
|
||||
description: >-
|
||||
Mixed authentication mode allows the use of Windows
|
||||
credentials but supplements them with local SQL Server user
|
||||
accounts that the administrator may create and maintain within
|
||||
SQL Server. If this mode is on SA password is required
|
||||
- name: saPassword
|
||||
type: password
|
||||
label: SA Password
|
||||
description: Set system administrator password for the MS SQL Server.
|
||||
helpText: SQL server System Administrator account
|
||||
required: {YAQL: $.serviceConfiguration.mixedModeAuth}
|
||||
- clusterConfiguration:
|
||||
fields:
|
||||
- name: clusterIP
|
||||
type: clusterip
|
||||
label: Cluster Static IP
|
||||
description: Specify a valid IPv4 fixed IP.
|
||||
- name: clusterName
|
||||
type: string
|
||||
label: Cluster Name
|
||||
helpText: Service name for new SQL Cluster service
|
||||
description: >-
|
||||
Specify a name of a cluster. Just A-Z, a-z, 0-9, dash and underline are allowed.
|
||||
- name: agGroupName
|
||||
type: string
|
||||
label: Availability Group Name
|
||||
helpText: Name of AG during SQL setup
|
||||
description: >-
|
||||
Specify a name of an AG. Just A-Z, a-z, 0-9, dash and underline are allowed.
|
||||
- name: agListenerName
|
||||
type: string
|
||||
label: Availability Group Listener Name
|
||||
helpText: FQDN name of a new DNS entry for AG Listener endpoint
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
description: >-
|
||||
Specify a name of an AG Listener . Just A-Z, a-z, 0-9, dash and underline are allowed.
|
||||
- name: agListenerIP
|
||||
type: clusterip
|
||||
label: Availability Group Listener IP
|
||||
description: Specify a valid IPv4 fixed IP.
|
||||
- name: sqlServiceUserName
|
||||
type: string
|
||||
label: SQL User Name
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
description: User name that will be created to manage cluster instances.
|
||||
- name: sqlServicePassword
|
||||
type: password
|
||||
label: SQL User Password
|
||||
description: User password that will be created to manage cluster instances.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
label: Instance Count
|
||||
minValue: 2
|
||||
maxValue: 5
|
||||
initial: 2
|
||||
attributeNames: false
|
||||
helpText: Enter an integer value between 2 and 5
|
||||
description: Microsoft SQL Failover Cluster includes up to 5 instances.
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions.
|
||||
required: false
|
||||
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
validators:
|
||||
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
|
||||
- expr: {YAQL: not $.clusterConfiguration.unitNamingPattern.bool() or '#' in $.clusterConfiguration.unitNamingPattern}
|
||||
message: Incrementation symbol "#" is required in the Hostname template
|
||||
# if IP is not valid on its own, it will be empty - the
|
||||
# first check is needed to not emit comparison error when
|
||||
# both IPs are not valid
|
||||
- expr: {YAQL: not $.clusterConfiguration.clusterIP.bool() or $.clusterConfiguration.clusterIP != $.clusterConfiguration.agListenerIP}
|
||||
message: Listener IP and Cluster Static IP should be different
|
||||
- unitsConfiguration:
|
||||
fields:
|
||||
- name: nodes
|
||||
type: datagrid
|
||||
label: Nodes
|
||||
initial: {YAQL: $.clusterConfiguration.dcInstances}
|
||||
description: >-
|
||||
Configure cluster instances. Cluster node quantity can be set
|
||||
with 'Add' and 'Remove' buttons. Configure Sync mode by
|
||||
enabling corresponding checkbox. All other nodes will be in
|
||||
Async mode. Just 2 nodes are allowed to be Sync. Also one
|
||||
Master node need to be selected. SQL Failover cluster has
|
||||
limit of 5 instances.
|
||||
- name: databases
|
||||
type: databaselist
|
||||
label: Database list
|
||||
description: >-
|
||||
Specify names for new databases which will be created as part
|
||||
of service installation. Here should come comma-separated list
|
||||
of database names, where each name has the following syntax:
|
||||
first symbol should be latin letter or underscore; subsequent
|
||||
symbols can be latin letter, numeric, underscore, at sign,
|
||||
number sign or dollar sign.
|
||||
helpText: Enter comma separated list of databases that will be created
|
||||
- instanceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
110
muranodashboard/services/MsSqlServer.yaml
Normal file
110
muranodashboard/services/MsSqlServer.yaml
Normal file
@ -0,0 +1,110 @@
|
||||
name: MS SQL Server
|
||||
type: msSqlServer
|
||||
|
||||
description: >-
|
||||
<strong> The MS SQL Service </strong> installs an instance of
|
||||
Microsoft SQL Server
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- serviceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: MS SQL Server
|
||||
# temporaryHack
|
||||
widgetMedia:
|
||||
js: [muranodashboard/js/mixed-mode.js]
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
hidden: true
|
||||
attributeNames: units
|
||||
initial: 1
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 7 characters.
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: mixedModeAuth
|
||||
type: boolean
|
||||
label: Mixed-mode Authentication
|
||||
initial: true
|
||||
required: false
|
||||
description: >-
|
||||
Mixed authentication mode allows the use of Windows
|
||||
credentials but supplements them with local SQL Server user
|
||||
accounts that the administrator may create and maintain within
|
||||
SQL Server. If this mode is on SA password is required
|
||||
- name: saPassword
|
||||
type: password
|
||||
label: SA Password
|
||||
description: Set system administrator password for the MS SQL Server.
|
||||
helpText: SQL server System Administrator account
|
||||
required: {YAQL: $.serviceConfiguration.mixedModeAuth}
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions.
|
||||
required: false
|
||||
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- instanceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
91
muranodashboard/services/WebServer.yaml
Normal file
91
muranodashboard/services/WebServer.yaml
Normal file
@ -0,0 +1,91 @@
|
||||
name: Internet Information Services
|
||||
type: webServer
|
||||
|
||||
description: >-
|
||||
<strong> The Internet Information Service </strong>
|
||||
sets up an IIS server and joins it into an existing domain
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- serviceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
description: Standalone IIS Server
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
hidden: true
|
||||
attributeNames: units
|
||||
initial: 1
|
||||
- name: adminPassword
|
||||
type: password
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 7 characters.
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions.
|
||||
required: false
|
||||
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
- instanceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
112
muranodashboard/services/WebServerFarm.yaml
Normal file
112
muranodashboard/services/WebServerFarm.yaml
Normal file
@ -0,0 +1,112 @@
|
||||
name: Internet Information Services Web Farm
|
||||
type: webServerFarm
|
||||
|
||||
description: >-
|
||||
<strong> The IIS Farm Service </strong> sets up a load-balanced set of IIS servers
|
||||
|
||||
unitTemplates:
|
||||
- {}
|
||||
|
||||
forms:
|
||||
- serviceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
hidden: true
|
||||
required: false
|
||||
attributeNames: false
|
||||
description: A load-balanced array of IIS servers
|
||||
- name: name
|
||||
type: string
|
||||
label: Service Name
|
||||
description: >-
|
||||
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
|
||||
underline are allowed.
|
||||
minLength: 2
|
||||
maxLength: 64
|
||||
regexpValidator: '^[-\w]+$'
|
||||
errorMessages:
|
||||
invalid: Just letters, numbers, underscores and hyphens are allowed.
|
||||
helpText: Just letters, numbers, underscores and hyphens are allowed.
|
||||
- name: username
|
||||
type: string
|
||||
hidden: true
|
||||
initial: Administrator
|
||||
attributeNames: credentials.username
|
||||
- name: adminPassword
|
||||
type: password
|
||||
attributeNames: [adminPassword, credentials.password]
|
||||
label: Administrator password
|
||||
descriptionTitle: Passwords
|
||||
description: >-
|
||||
Windows requires strong password for service administration.
|
||||
Your password should have at least one letter in each
|
||||
register, a number and a special character. Password length should be
|
||||
a minimum of 7 characters.
|
||||
- name: domain
|
||||
type: domain
|
||||
label: Domain
|
||||
required: false
|
||||
description: >-
|
||||
Service can be joined to the Active Directory domain. If you want to
|
||||
create an AD domain create the AD Service first.
|
||||
helpText: Optional field for a domain to which service can be joined
|
||||
- name: dcInstances
|
||||
type: instance
|
||||
minValue: 2
|
||||
maxValue: 100
|
||||
attributeNames: [units, instanceCount]
|
||||
initial: 2
|
||||
label: Instance Count
|
||||
description: Several instances with IIS Service can be created at one time.
|
||||
helpText: Enter an integer value between 2 and 100
|
||||
- name: loadBalancerPort
|
||||
type: integer
|
||||
label: Load Balancer port
|
||||
minValue: 1
|
||||
maxValue: 65536
|
||||
initial: 80
|
||||
description: Specify port number where Load Balancer will be running
|
||||
helpText: Enter an integer value from 1 to 65536
|
||||
- name: unitNamingPattern
|
||||
type: string
|
||||
label: Hostname template
|
||||
description: >-
|
||||
For your convenience all instance hostnames can be named
|
||||
in the same way. Enter a name and use # character for incrementation.
|
||||
For example, host# turns into host1, host2, etc. Please follow Windows
|
||||
hostname restrictions.
|
||||
required: false
|
||||
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
|
||||
helpText: Optional field for a machine hostname template
|
||||
validators:
|
||||
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
|
||||
- expr: {YAQL: not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
|
||||
message: Incrementation symbol "#" is required in the Hostname template
|
||||
- instanceConfiguration:
|
||||
fields:
|
||||
- name: title
|
||||
type: string
|
||||
required: false
|
||||
hidden: true
|
||||
attributeNames: false
|
||||
descriptionTitle: Instance Configuration
|
||||
description: Specify some instance parameters on which service would be created.
|
||||
- name: flavor
|
||||
type: flavor
|
||||
label: Instance flavor
|
||||
description: >-
|
||||
Select registered in Openstack flavor. Consider that service performance
|
||||
depends on this parameter.
|
||||
required: false
|
||||
- name: osImage
|
||||
type: image
|
||||
label: Instance image
|
||||
description: >-
|
||||
Select valid image for a service. Image should already be prepared and
|
||||
registered in glance.
|
||||
- name: availabilityZone
|
||||
type: azone
|
||||
label: Availability zone
|
||||
description: Select availability zone where service would be installed.
|
||||
required: false
|
@ -123,8 +123,8 @@ $(function() {
|
||||
}
|
||||
data.push({
|
||||
name: trimLabel($(tr).children().eq(0).text()),
|
||||
is_sync: getInputVal($(tr).children().eq(1)),
|
||||
is_primary: getInputVal($(tr).children().eq(2))
|
||||
isSync: getInputVal($(tr).children().eq(1)),
|
||||
isMaster: getInputVal($(tr).children().eq(2))
|
||||
})
|
||||
});
|
||||
$('input.gridfield-hidden').val(JSON.stringify(data));
|
||||
|
@ -33,8 +33,8 @@
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<h3>{% trans "Description" %}:</h3>
|
||||
{% for slug, description in service_descriptions %}
|
||||
<p class="switchable" id="{{ slug }}">
|
||||
{% for service_type, description in service_descriptions %}
|
||||
<p class="switchable" id="{{ service_type }}">
|
||||
{% autoescape off %} {% blocktrans %}
|
||||
{{ description }}
|
||||
{% endblocktrans %} {% endautoescape %}</p>
|
||||
|
@ -8,4 +8,5 @@ PyYAML
|
||||
django-pipeline
|
||||
django-floppyforms==1.1
|
||||
ordereddict
|
||||
yaql==0.2
|
||||
http://tarballs.openstack.org/python-muranoclient/python-muranoclient-release-0.2.tar.gz#egg=muranoclient-dev
|
||||
|
@ -17,14 +17,13 @@
|
||||
|
||||
LOGLVL=1
|
||||
SERVICE_CONTENT_DIRECTORY=`cd $(dirname "$0") && pwd`
|
||||
DJBLETS_ZIP_URL=https://github.com/tsufiev/djblets/archive
|
||||
PREREQ_PKGS="wget make git python-pip mysql-connector-python python-devel unzip libffi-devel"
|
||||
PIPAPPS="pip python-pip pip-python"
|
||||
PIPCMD=""
|
||||
SERVICE_SRV_NAME="murano-dashboard"
|
||||
GIT_CLONE_DIR=`echo $SERVICE_CONTENT_DIRECTORY | sed -e "s/$SERVICE_SRV_NAME//"`
|
||||
HORIZON_CONFIGS="/opt/stack/horizon/openstack_dashboard/settings.py,/usr/share/openstack-dashboard/openstack_dashboard/settings.py"
|
||||
|
||||
NON_PIP_PACKAGES_BASE_URL=https://github.com
|
||||
# Functions
|
||||
# Loger function
|
||||
log()
|
||||
@ -171,6 +170,14 @@ rebuildstatic()
|
||||
log "openstack-dashboard manage.py not found, exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
_old_murano_static="$(dirname $horizon_manage)/openstack_dashboard/static/muranodashboard"
|
||||
if [ -d "$_old_murano_static" ];then
|
||||
log "Our staic for \"muranodashboard\" found under \"HORIZON\" STATIC, deleting \"$_old_murano_static\"..."
|
||||
rm -rf $_old_murano_static
|
||||
if [ $? -ne 0 ]; then
|
||||
log "Can't delete \"$_old_murano_static\, WARNING!!!"
|
||||
fi
|
||||
fi
|
||||
log "Rebuilding STATIC...."
|
||||
python $horizon_manage collectstatic --noinput
|
||||
if [ $? -ne 0 ]; then
|
||||
@ -243,28 +250,35 @@ CLONE_FROM_GIT=$1
|
||||
log "$PIPCMD install \"$TRBL_FILE\" FAILS, exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
# DJBLETS INSTALL START
|
||||
DJBLETS_SUFFIX=master.zip
|
||||
DJBLETS_OUTARCH_FILENAME=djblets-$DJBLETS_SUFFIX
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && wget $DJBLETS_ZIP_URL/$DJBLETS_SUFFIX -O $DJBLETS_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't download \"$DJBLETS_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && unzip $DJBLETS_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't unzip \"$SERVICE_CONTENT_DIRECTORY/dist/$DJBLETS_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist/djblets-master && python setup.py install
|
||||
if [ $? -ne 0 ]; then
|
||||
log "\"$SERVICE_CONTENT_DIRECTORY/dist/djblets-master/setup.py\" python setup FAILS, exiting!"
|
||||
# NON PIP PACKAGES INSTALL START
|
||||
for pkg in tsufiev.djblets; do
|
||||
PACKAGE=${pkg##*.}
|
||||
OWNER=${pkg%.*}
|
||||
SUFFIX=master.zip
|
||||
PACKAGE_OUTARCH_FILENAME=$PACKAGE-$SUFFIX
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && wget $NON_PIP_PACKAGES_BASE_URL/$OWNER/$PACKAGE/archive/$SUFFIX -O $PACKAGE_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't download \"$PACKAGE_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && unzip $PACKAGE_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't unzip \"$SERVICE_CONTENT_DIRECTORY/dist/$PACKAGE_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist/$PACKAGE-${SUFFIX%.*} && python setup.py install
|
||||
if [ $? -ne 0 ]; then
|
||||
log "\"$SERVICE_CONTENT_DIRECTORY/dist/$PACKAGE-${SUFFIX%.*}/setup.py\" python setup FAILS, exiting!"
|
||||
exit 1
|
||||
fi
|
||||
# DJBLETS INSTALL END
|
||||
fi
|
||||
done
|
||||
# NON PIP PACKAGES INSTALL END
|
||||
else
|
||||
log "$MRN_CND_SPY not found!"
|
||||
fi
|
||||
# add apache to autostart
|
||||
chkconfig --add httpd
|
||||
chkconfig httpd on
|
||||
}
|
||||
|
||||
# uninstall
|
||||
|
54
setup.sh
54
setup.sh
@ -21,7 +21,7 @@ PREREQ_PKGS="wget make git python-pip python-dev python-mysqldb libxml2-dev libx
|
||||
SERVICE_SRV_NAME="murano-dashboard"
|
||||
GIT_CLONE_DIR=`echo $SERVICE_CONTENT_DIRECTORY | sed -e "s/$SERVICE_SRV_NAME//"`
|
||||
HORIZON_CONFIGS="/opt/stack/horizon/openstack_dashboard/settings.py,/usr/share/openstack-dashboard/openstack_dashboard/settings.py"
|
||||
DJBLETS_ZIP_URL=https://github.com/tsufiev/djblets/archive
|
||||
NON_PIP_PACKAGES_BASE_URL=https://github.com
|
||||
|
||||
# Functions
|
||||
# Logger function
|
||||
@ -187,26 +187,30 @@ CLONE_FROM_GIT=$1
|
||||
log "pip install \"$TRBL_FILE\" FAILS, exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
# DJBLETS INSTALL START
|
||||
DJBLETS_SUFFIX=master.zip
|
||||
DJBLETS_OUTARCH_FILENAME=djblets-$DJBLETS_SUFFIX
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && wget $DJBLETS_ZIP_URL/$DJBLETS_SUFFIX -O $DJBLETS_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't download \"$DJBLETS_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && unzip $DJBLETS_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't unzip \"$SERVICE_CONTENT_DIRECTORY/dist/$DJBLETS_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist/djblets-master && python setup.py install
|
||||
if [ $? -ne 0 ]; then
|
||||
log "\"$SERVICE_CONTENT_DIRECTORY/dist/djblets-master/setup.py\" python setup FAILS, exiting!"
|
||||
exit 1
|
||||
# NON PIP PACKAGES INSTALL START
|
||||
for pkg in tsufiev.djblets; do
|
||||
PACKAGE=${pkg##*.}
|
||||
OWNER=${pkg%.*}
|
||||
SUFFIX=master.zip
|
||||
PACKAGE_OUTARCH_FILENAME=$PACKAGE-$SUFFIX
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && wget $NON_PIP_PACKAGES_BASE_URL/$OWNER/$PACKAGE/archive/$SUFFIX -O $PACKAGE_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't download \"$PACKAGE_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
# DJBLETS INSTALL END
|
||||
else
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist && unzip $PACKAGE_OUTARCH_FILENAME
|
||||
if [ $? -ne 0 ];then
|
||||
log " Can't unzip \"$SERVICE_CONTENT_DIRECTORY/dist/$PACKAGE_OUTARCH_FILENAME\", exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
cd $SERVICE_CONTENT_DIRECTORY/dist/$PACKAGE-${SUFFIX%.*} && python setup.py install
|
||||
if [ $? -ne 0 ]; then
|
||||
log "\"$SERVICE_CONTENT_DIRECTORY/dist/$PACKAGE-${SUFFIX%.*}/setup.py\" python setup FAILS, exiting!"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
# NON PIP PACKAGES INSTALL END
|
||||
else
|
||||
log "$MRN_CND_SPY not found!"
|
||||
fi
|
||||
}
|
||||
@ -233,7 +237,7 @@ preinst()
|
||||
dpkg -s $_PKG > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
log "Package \"$_PKG\" is not installed."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# rebuild static
|
||||
@ -244,6 +248,14 @@ rebuildstatic()
|
||||
log "openstack-dashboard manage.py not found, exiting!!!"
|
||||
exit 1
|
||||
fi
|
||||
_old_murano_static="$(dirname $horizon_manage)/openstack_dashboard/static/muranodashboard"
|
||||
if [ -d "$_old_murano_static" ];then
|
||||
log "Our staic for \"muranodashboard\" found under \"HORIZON\" STATIC, deleting \"$_old_murano_static\"..."
|
||||
rm -rf $_old_murano_static
|
||||
if [ $? -ne 0 ]; then
|
||||
log "Can't delete \"$_old_murano_static\, WARNING!!!"
|
||||
fi
|
||||
fi
|
||||
log "Rebuilding STATIC...."
|
||||
python $horizon_manage collectstatic --noinput
|
||||
if [ $? -ne 0 ]; then
|
||||
|
Loading…
Reference in New Issue
Block a user