summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Gajsin <igajsin@mirantis.com>2017-02-02 22:52:41 +0300
committerIgor Gajsin <igajsin@mirantis.com>2017-02-14 15:52:27 +0000
commit634b66df450239378a2dfff2797422c6de053af8 (patch)
tree28ab0cbdcf81c3948c57b8a780cafded7fda0e05
parentc77aa8923a59675d2474ef448d92663a31d5619c (diff)
remove vmware
VMware not supported since Fuel 10. Implements: blueprint remove-vmware Change-Id: Ia26a97d13bb9c3d2e838d639efdababbb15f86da
Notes
Notes (review): Code-Review+1: Georgy Kibardin <gkibardin@mirantis.com> Code-Review+1: Julia Aranovich <jkirnosova@mirantis.com> Verified+1: Fuel CI <fuel-ci-bot@mirantis.com> Code-Review+1: Fedor Zhadaev <fzhadaev@mirantis.com> Code-Review+1: Oleksiy Molchanov <omolchanov@mirantis.com> Code-Review+1: Alexander Arzhanov <aarzhanov@mirantis.com> Code-Review+2: Aleksey Kasatkin <akasatkin@mirantis.com> Code-Review+2: Ihor Kalnytskyi <ikalnitsky@mirantis.com> Workflow+1: Ihor Kalnytskyi <ikalnitsky@mirantis.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Tue, 21 Feb 2017 13:06:39 +0000 Reviewed-on: https://review.openstack.org/428402 Project: openstack/fuel-web Branch: refs/heads/master
-rw-r--r--nailgun/nailgun/api/v1/handlers/cluster.py121
-rw-r--r--nailgun/nailgun/api/v1/urls.py7
-rw-r--r--nailgun/nailgun/api/v1/validators/cluster.py262
-rw-r--r--nailgun/nailgun/api/v1/validators/json_schema/cluster.py11
-rw-r--r--nailgun/nailgun/consts.py3
-rw-r--r--nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_10_0.py78
-rw-r--r--nailgun/nailgun/db/sqlalchemy/models/__init__.py1
-rw-r--r--nailgun/nailgun/db/sqlalchemy/models/cluster.py9
-rw-r--r--nailgun/nailgun/db/sqlalchemy/models/release.py2
-rw-r--r--nailgun/nailgun/fixtures/openstack.yaml268
-rw-r--r--nailgun/nailgun/fixtures/sample_plugins.json6
-rw-r--r--nailgun/nailgun/fixtures/vmware_attributes.json245
-rw-r--r--nailgun/nailgun/objects/__init__.py1
-rw-r--r--nailgun/nailgun/objects/cluster.py111
-rw-r--r--nailgun/nailgun/objects/serializers/release.py1
-rw-r--r--nailgun/nailgun/orchestrator/base_serializers.py102
-rw-r--r--nailgun/nailgun/orchestrator/deployment_serializers.py66
-rw-r--r--nailgun/nailgun/plugins/adapters.py2
-rw-r--r--nailgun/nailgun/statistics/fuel_statistics/installation_info.py20
-rw-r--r--nailgun/nailgun/task/task.py97
-rw-r--r--nailgun/nailgun/test/base.py8
-rw-r--r--nailgun/nailgun/test/integration/test_attributes.py226
-rw-r--r--nailgun/nailgun/test/integration/test_changes_model.py12
-rw-r--r--nailgun/nailgun/test/integration/test_cluster_collection_handlers.py1
-rw-r--r--nailgun/nailgun/test/integration/test_orchestrator_serializer.py168
-rw-r--r--nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py29
-rw-r--r--nailgun/nailgun/test/unit/fuel_statistics_tests/test_installation_info.py45
-rw-r--r--nailgun/nailgun/test/unit/test_deployment_graph_object.py6
-rw-r--r--nailgun/nailgun/test/unit/test_objects.py21
-rw-r--r--nailgun/nailgun/test/unit/test_restriction.py144
-rw-r--r--nailgun/nailgun/test/unit/test_task.py90
-rw-r--r--nailgun/nailgun/test/unit/test_vmware_attributes_validator.py443
-rw-r--r--nailgun/nailgun/utils/restrictions.py81
33 files changed, 91 insertions, 2596 deletions
diff --git a/nailgun/nailgun/api/v1/handlers/cluster.py b/nailgun/nailgun/api/v1/handlers/cluster.py
index c10c959..d3eb6ce 100644
--- a/nailgun/nailgun/api/v1/handlers/cluster.py
+++ b/nailgun/nailgun/api/v1/handlers/cluster.py
@@ -38,7 +38,6 @@ from nailgun.api.v1.validators.cluster import ClusterAttributesValidator
38from nailgun.api.v1.validators.cluster import ClusterChangesValidator 38from nailgun.api.v1.validators.cluster import ClusterChangesValidator
39from nailgun.api.v1.validators.cluster import ClusterStopDeploymentValidator 39from nailgun.api.v1.validators.cluster import ClusterStopDeploymentValidator
40from nailgun.api.v1.validators.cluster import ClusterValidator 40from nailgun.api.v1.validators.cluster import ClusterValidator
41from nailgun.api.v1.validators.cluster import VmwareAttributesValidator
42 41
43from nailgun.api.v1.validators.extension import ExtensionValidator 42from nailgun.api.v1.validators.extension import ExtensionValidator
44from nailgun import errors 43from nailgun import errors
@@ -435,120 +434,6 @@ class ClusterOwnDeploymentTasksHandler(BaseHandler):
435 return tasks 434 return tasks
436 435
437 436
438class VmwareAttributesHandler(BaseHandler):
439 """Vmware attributes handler"""
440
441 fields = (
442 "editable",
443 )
444
445 validator = VmwareAttributesValidator
446
447 @handle_errors
448 @validate
449 @serialize
450 def GET(self, cluster_id):
451 """:returns: JSONized Cluster vmware attributes.
452
453 :http: * 200 (OK)
454 * 400 (cluster doesn't accept vmware configuration)
455 * 404 (cluster not found in db |
456 cluster has no vmware attributes)
457 """
458 cluster = self.get_object_or_404(
459 objects.Cluster, cluster_id,
460 log_404=(
461 "error",
462 "There is no cluster "
463 "with id '{0}' in DB.".format(cluster_id)
464 )
465 )
466 if not objects.Cluster.is_vmware_enabled(cluster):
467 raise self.http(400, "Cluster doesn't support vmware "
468 "configuration")
469
470 attributes = objects.Cluster.get_vmware_attributes(cluster)
471 if not attributes:
472 raise self.http(404, "No vmware attributes found")
473
474 return self.render(attributes)
475
476 @handle_errors
477 @validate
478 @serialize
479 def PUT(self, cluster_id):
480 """:returns: JSONized Cluster vmware attributes.
481
482 :http: * 200 (OK)
483 * 400 (wrong attributes data specified |
484 cluster doesn't accept vmware configuration)
485 * 403 (attributes can't be changed)
486 * 404 (cluster not found in db |
487 cluster has no vmware attributes)
488 """
489 cluster = self.get_object_or_404(
490 objects.Cluster, cluster_id,
491 log_404=(
492 "error",
493 "There is no cluster "
494 "with id '{0}' in DB.".format(cluster_id)
495 )
496 )
497 if not objects.Cluster.is_vmware_enabled(cluster):
498 raise self.http(400, "Cluster doesn't support vmware "
499 "configuration")
500
501 attributes = objects.Cluster.get_vmware_attributes(cluster)
502 if not attributes:
503 raise self.http(404, "No vmware attributes found")
504
505 if cluster.is_locked and \
506 not objects.Cluster.has_compute_vmware_changes(cluster):
507 raise self.http(403, "Environment attributes can't be changed "
508 "after or during deployment.")
509
510 data = self.checked_data(instance=attributes)
511 attributes = objects.Cluster.update_vmware_attributes(cluster, data)
512
513 return {"editable": attributes}
514
515
516class VmwareAttributesDefaultsHandler(BaseHandler):
517 """Vmware default attributes handler"""
518
519 @handle_errors
520 @validate
521 @serialize
522 def GET(self, cluster_id):
523 """:returns: JSONized default Cluster vmware attributes.
524
525 :http: * 200 (OK)
526 * 400 (cluster doesn't accept vmware configuration)
527 * 404 (cluster not found in db)
528 """
529 cluster = self.get_object_or_404(
530 objects.Cluster, cluster_id,
531 log_404=(
532 "error",
533 "There is no cluster "
534 "with id '{0}' in DB.".format(cluster_id)
535 )
536 )
537 if not objects.Cluster.is_vmware_enabled(cluster):
538 raise self.http(400, "Cluster doesn't support vmware "
539 "configuration")
540
541 attributes = objects.Cluster.get_default_vmware_attributes(cluster)
542
543 return {"editable": attributes}
544
545
546class ClusterDeploymentGraphHandler(RelatedDeploymentGraphHandler):
547 """Cluster Handler for deployment graph configuration."""
548
549 related = objects.Cluster
550
551
552class ClusterDeploymentGraphCollectionHandler( 437class ClusterDeploymentGraphCollectionHandler(
553 RelatedDeploymentGraphCollectionHandler): 438 RelatedDeploymentGraphCollectionHandler):
554 """Cluster Handler for deployment graphs configuration.""" 439 """Cluster Handler for deployment graphs configuration."""
@@ -618,3 +503,9 @@ class ClusterExtensionsHandler(BaseHandler):
618 503
619 remove_extensions_from_object(cluster, data) 504 remove_extensions_from_object(cluster, data)
620 raise self.http(204) 505 raise self.http(204)
506
507
508class ClusterDeploymentGraphHandler(RelatedDeploymentGraphHandler):
509 """Cluster Handler for deployment graph configuration."""
510
511 related = objects.Cluster
diff --git a/nailgun/nailgun/api/v1/urls.py b/nailgun/nailgun/api/v1/urls.py
index ee472ac..9786cad 100644
--- a/nailgun/nailgun/api/v1/urls.py
+++ b/nailgun/nailgun/api/v1/urls.py
@@ -44,8 +44,6 @@ from nailgun.api.v1.handlers.cluster import \
44 ClusterReleaseDeploymentTasksHandler 44 ClusterReleaseDeploymentTasksHandler
45from nailgun.api.v1.handlers.cluster import ClusterResetHandler 45from nailgun.api.v1.handlers.cluster import ClusterResetHandler
46from nailgun.api.v1.handlers.cluster import ClusterStopDeploymentHandler 46from nailgun.api.v1.handlers.cluster import ClusterStopDeploymentHandler
47from nailgun.api.v1.handlers.cluster import VmwareAttributesDefaultsHandler
48from nailgun.api.v1.handlers.cluster import VmwareAttributesHandler
49from nailgun.api.v1.handlers.component import ComponentCollectionHandler 47from nailgun.api.v1.handlers.component import ComponentCollectionHandler
50 48
51from nailgun.api.v1.handlers.cluster_plugin_link \ 49from nailgun.api.v1.handlers.cluster_plugin_link \
@@ -270,11 +268,6 @@ urls = (
270 r'/clusters/(?P<cluster_id>\d+)/unassignment/?$', 268 r'/clusters/(?P<cluster_id>\d+)/unassignment/?$',
271 NodeUnassignmentHandler, 269 NodeUnassignmentHandler,
272 270
273 r'/clusters/(?P<cluster_id>\d+)/vmware_attributes/?$',
274 VmwareAttributesHandler,
275 r'/clusters/(?P<cluster_id>\d+)/vmware_attributes/defaults/?$',
276 VmwareAttributesDefaultsHandler,
277
278 r'/clusters/(?P<cluster_id>\d+)/plugin_links/?$', 271 r'/clusters/(?P<cluster_id>\d+)/plugin_links/?$',
279 ClusterPluginLinkCollectionHandler, 272 ClusterPluginLinkCollectionHandler,
280 r'/clusters/(?P<cluster_id>\d+)/plugin_links/(?P<obj_id>\d+)/?$', 273 r'/clusters/(?P<cluster_id>\d+)/plugin_links/(?P<obj_id>\d+)/?$',
diff --git a/nailgun/nailgun/api/v1/validators/cluster.py b/nailgun/nailgun/api/v1/validators/cluster.py
index 7cedc66..ad4b5be 100644
--- a/nailgun/nailgun/api/v1/validators/cluster.py
+++ b/nailgun/nailgun/api/v1/validators/cluster.py
@@ -297,265 +297,3 @@ class ClusterStopDeploymentValidator(base.BaseDefferedTaskValidator):
297 raise errors.CannotBeStopped('Current deployment process is ' 297 raise errors.CannotBeStopped('Current deployment process is '
298 'running on a pre-deployed cluster ' 298 'running on a pre-deployed cluster '
299 'that does not support LCM.') 299 'that does not support LCM.')
300
301
302class VmwareAttributesValidator(base.BasicValidator):
303
304 single_schema = cluster_schema.vmware_attributes_schema
305
306 @staticmethod
307 def _get_target_node_id(nova_compute_data):
308 return nova_compute_data['target_node']['current']['id']
309
310 @classmethod
311 def _validate_updated_attributes(cls, attributes, instance):
312 """Validate that attributes contains changes only for allowed fields.
313
314 :param attributes: new vmware attribute settings for db instance
315 :param instance: nailgun.db.sqlalchemy.models.VmwareAttributes instance
316 """
317 metadata = instance.editable.get('metadata', {})
318 db_editable_attributes = instance.editable.get('value', {})
319 new_editable_attributes = attributes.get('editable', {}).get('value')
320 for attribute_metadata in metadata:
321 if attribute_metadata.get('type') == 'array':
322 attribute_name = attribute_metadata['name']
323 cls._check_attribute(
324 attribute_metadata,
325 db_editable_attributes.get(attribute_name),
326 new_editable_attributes.get(attribute_name)
327 )
328 else:
329 cls._check_attribute(
330 attribute_metadata,
331 db_editable_attributes,
332 new_editable_attributes
333 )
334
335 @classmethod
336 def _check_attribute(cls, metadata, attributes, new_attributes):
337 """Check new_attributes is equal with attributes except editable fields
338
339 :param metadata: dict describes structure and properties of attributes
340 :param attributes: attributes which is the basis for comparison
341 :param new_attributes: attributes with modifications to check
342 """
343 if type(attributes) != type(new_attributes):
344 raise errors.InvalidData(
345 "Value type of '{0}' attribute couldn't be changed.".
346 format(metadata.get('label') or metadata.get('name')),
347 log_message=True
348 )
349 # if metadata field contains editable_for_deployed = True, attribute
350 # and all its childs may be changed too. No need to check it.
351 if metadata.get('editable_for_deployed'):
352 return
353
354 # no 'fields' in metadata means that attribute has no any childs(leaf)
355 if 'fields' not in metadata:
356 if attributes != new_attributes:
357 raise errors.InvalidData(
358 "Value of '{0}' attribute couldn't be changed.".
359 format(metadata.get('label') or metadata.get('name')),
360 log_message=True
361 )
362 return
363
364 fields_sort_functions = {
365 'availability_zones': lambda x: x['az_name'],
366 'nova_computes': lambda x: x['vsphere_cluster']
367 }
368 field_name = metadata['name']
369 if isinstance(attributes, (list, tuple)):
370 if len(attributes) != len(new_attributes):
371 raise errors.InvalidData(
372 "Value of '{0}' attribute couldn't be changed.".
373 format(metadata.get('label') or metadata.get('name')),
374 log_message=True
375 )
376 attributes = sorted(
377 attributes, key=fields_sort_functions.get(field_name))
378 new_attributes = sorted(
379 new_attributes, key=fields_sort_functions.get(field_name))
380 for item, new_item in six.moves.zip(attributes, new_attributes):
381 for field_metadata in metadata['fields']:
382 cls._check_attribute(field_metadata,
383 item.get(field_metadata['name']),
384 new_item.get(field_metadata['name']))
385 elif isinstance(attributes, dict):
386 for field_metadata in metadata['fields']:
387 cls._check_attribute(field_metadata,
388 attributes.get(field_name),
389 new_attributes.get(field_name))
390
391 @classmethod
392 def _validate_nova_computes(cls, attributes, instance):
393 """Validates a 'nova_computes' attributes from vmware_attributes
394
395 Raise InvalidData exception if new attributes is not valid.
396
397 :param instance: nailgun.db.sqlalchemy.models.VmwareAttributes instance
398 :param attributes: new attributes for db instance for validation
399 """
400 input_nova_computes = objects.VmwareAttributes.get_nova_computes_attrs(
401 attributes.get('editable'))
402
403 cls.check_nova_compute_duplicate_and_empty_values(input_nova_computes)
404
405 db_nova_computes = objects.VmwareAttributes.get_nova_computes_attrs(
406 instance.editable)
407 if instance.cluster.is_locked:
408 cls.check_operational_controllers_settings(input_nova_computes,
409 db_nova_computes)
410 operational_compute_nodes = objects.Cluster.\
411 get_operational_vmware_compute_nodes(instance.cluster)
412 cls.check_operational_node_settings(
413 input_nova_computes, db_nova_computes, operational_compute_nodes)
414
415 @classmethod
416 def check_nova_compute_duplicate_and_empty_values(cls, attributes):
417 """Check 'nova_computes' attributes for empty and duplicate values."""
418 nova_compute_attributes_sets = {
419 'vsphere_cluster': set(),
420 'service_name': set(),
421 'target_node': set()
422 }
423 for nova_compute_data in attributes:
424 for attr, values in six.iteritems(nova_compute_attributes_sets):
425 if attr == 'target_node':
426 settings_value = cls._get_target_node_id(nova_compute_data)
427 if settings_value == 'controllers':
428 continue
429 else:
430 settings_value = nova_compute_data.get(attr)
431 if not settings_value:
432 raise errors.InvalidData(
433 "Empty value for attribute '{0}' is not allowed".
434 format(attr),
435 log_message=True
436 )
437 if settings_value in values:
438 raise errors.InvalidData(
439 "Duplicate value '{0}' for attribute '{1}' is "
440 "not allowed".format(settings_value, attr),
441 log_message=True
442 )
443 values.add(settings_value)
444
445 @classmethod
446 def check_operational_node_settings(cls, input_nova_computes,
447 db_nova_computes, operational_nodes):
448 """Validates a 'nova_computes' attributes for operational compute nodes
449
450 Raise InvalidData exception if nova_compute settings will be changed or
451 deleted for deployed nodes with role 'compute-vmware' that wasn't
452 marked for deletion
453
454 :param input_nova_computes: new nova_compute attributes
455 :type input_nova_computes: list of dicts
456 :param db_nova_computes: nova_computes attributes stored in db
457 :type db_nova_computes: list of dicts
458 :param operational_nodes: list of operational vmware-compute nodes
459 :type operational_nodes: list of nailgun.db.sqlalchemy.models.Node
460 """
461 input_computes_by_node_name = dict(
462 (cls._get_target_node_id(nc), nc) for nc in input_nova_computes)
463 db_computes_by_node_name = dict(
464 (cls._get_target_node_id(nc), nc) for nc in db_nova_computes)
465
466 for node in operational_nodes:
467 node_hostname = node.hostname
468 input_nova_compute = input_computes_by_node_name.get(node_hostname)
469 if not input_nova_compute:
470 raise errors.InvalidData(
471 "The following compute-vmware node couldn't be "
472 "deleted from vSphere cluster: {0}".format(node.name),
473 log_message=True
474 )
475 db_nova_compute = db_computes_by_node_name.get(node_hostname)
476 for attr, db_value in six.iteritems(db_nova_compute):
477 if attr != 'target_node' and \
478 db_value != input_nova_compute.get(attr):
479 raise errors.InvalidData(
480 "Parameter '{0}' of nova compute instance with target "
481 "node '{1}' couldn't be changed".format(
482 attr, node.name),
483 log_message=True
484 )
485
486 @classmethod
487 def check_operational_controllers_settings(cls, input_nova_computes,
488 db_nova_computes):
489 """Check deployed nova computes settings with target = controllers.
490
491 Raise InvalidData exception if any deployed nova computes clusters with
492 target 'controllers' were added, removed or modified.
493
494 :param input_nova_computes: new nova_compute settings
495 :type input_nova_computes: list of dicts
496 :param db_nova_computes: nova_computes settings stored in db
497 :type db_nova_computes: list of dicts
498 """
499 input_computes_by_vsphere_name = dict(
500 (nc['vsphere_cluster'], nc) for nc in input_nova_computes if
501 cls._get_target_node_id(nc) == 'controllers'
502 )
503 db_clusters_names = set()
504 for db_nova_compute in db_nova_computes:
505 target_name = cls._get_target_node_id(db_nova_compute)
506 if target_name == 'controllers':
507 vsphere_name = db_nova_compute['vsphere_cluster']
508 input_nova_compute = \
509 input_computes_by_vsphere_name.get(vsphere_name)
510 if not input_nova_compute:
511 raise errors.InvalidData(
512 "Nova compute instance with target 'controllers' and "
513 "vSphere cluster {0} couldn't be deleted from "
514 "operational environment.".format(vsphere_name),
515 log_message=True
516 )
517 for attr, db_value in six.iteritems(db_nova_compute):
518 input_value = input_nova_compute.get(attr)
519 if attr == 'target_node':
520 db_value = cls._get_target_node_id(db_nova_compute)
521 input_value = cls._get_target_node_id(
522 input_nova_compute)
523 if db_value != input_value:
524 raise errors.InvalidData(
525 "Parameter '{0}' of nova compute instance with "
526 "vSphere cluster name '{1}' couldn't be changed".
527 format(attr, vsphere_name),
528 log_message=True
529 )
530 db_clusters_names.add(vsphere_name)
531
532 input_clusters_names = set(input_computes_by_vsphere_name)
533 if input_clusters_names - db_clusters_names:
534 raise errors.InvalidData(
535 "Nova compute instances with target 'controllers' couldn't be "
536 "added to operational environment. Check nova compute "
537 "instances with the following vSphere cluster names: {0}".
538 format(', '.join(
539 sorted(input_clusters_names - db_clusters_names))),
540 log_message=True
541 )
542
543 @classmethod
544 def validate(cls, data, instance):
545 d = cls.validate_json(data)
546 if 'metadata' in d.get('editable'):
547 db_metadata = instance.editable.get('metadata')
548 input_metadata = d.get('editable').get('metadata')
549 if db_metadata != input_metadata:
550 raise errors.InvalidData(
551 'Metadata shouldn\'t change',
552 log_message=True
553 )
554
555 if instance.cluster.is_locked:
556 cls._validate_updated_attributes(d, instance)
557 cls._validate_nova_computes(d, instance)
558
559 # TODO(apopovych): write validation processing from
560 # openstack.yaml for vmware
561 return d
diff --git a/nailgun/nailgun/api/v1/validators/json_schema/cluster.py b/nailgun/nailgun/api/v1/validators/json_schema/cluster.py
index b46afd6..88dafd2 100644
--- a/nailgun/nailgun/api/v1/validators/json_schema/cluster.py
+++ b/nailgun/nailgun/api/v1/validators/json_schema/cluster.py
@@ -64,14 +64,3 @@ collection_schema = {
64 "type": "object", 64 "type": "object",
65 "items": single_schema["properties"] 65 "items": single_schema["properties"]
66} 66}
67
68vmware_attributes_schema = {
69 "$schema": "http://json-schema.org/draft-04/schema#",
70 "title": "Vmware attributes",
71 "description": "Serialized VmwareAttributes object",
72 "type": "object",
73 "required": ["editable"],
74 "properties": {
75 "editable": {"type": "object"}
76 }
77}
diff --git a/nailgun/nailgun/consts.py b/nailgun/nailgun/consts.py
index 93007ab..5490d6c 100644
--- a/nailgun/nailgun/consts.py
+++ b/nailgun/nailgun/consts.py
@@ -313,8 +313,7 @@ CLUSTER_CHANGES = Enum(
313 'networks', 313 'networks',
314 'attributes', 314 'attributes',
315 'disks', 315 'disks',
316 'interfaces', 316 'interfaces'
317 'vmware_attributes'
318) 317)
319 318
320PROVISION_METHODS = Enum( 319PROVISION_METHODS = Enum(
diff --git a/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_10_0.py b/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_10_0.py
index 52f8f3b..faac2b5 100644
--- a/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_10_0.py
+++ b/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_10_0.py
@@ -20,24 +20,41 @@ Create Date: 2016-04-08 15:20:43.989472
20 20
21""" 21"""
22 22
23
23from alembic import op 24from alembic import op
25from nailgun.db.sqlalchemy.models import fields
26from nailgun.utils.migration import upgrade_enum
24from oslo_serialization import jsonutils 27from oslo_serialization import jsonutils
25import sqlalchemy as sa 28import sqlalchemy as sa
26 29
27from nailgun.db.sqlalchemy.models import fields
28
29 30
30# revision identifiers, used by Alembic. 31# revision identifiers, used by Alembic.
31revision = 'c6edea552f1e' 32revision = 'c6edea552f1e'
32down_revision = '3763c404ca48' 33down_revision = '3763c404ca48'
33 34
35cluster_changes_old = (
36 'networks',
37 'attributes',
38 'disks',
39 'interfaces',
40 'vmware_attributes'
41)
42cluster_changes_new = (
43 'networks',
44 'attributes',
45 'disks',
46 'interfaces',
47)
48
34 49
35def upgrade(): 50def upgrade():
36 upgrade_plugin_links_constraints() 51 upgrade_plugin_links_constraints()
37 upgrade_release_required_component_types() 52 upgrade_release_required_component_types()
53 upgrade_remove_vmware()
38 54
39 55
40def downgrade(): 56def downgrade():
57 downgrade_remove_vmware()
41 downgrade_release_required_component_types() 58 downgrade_release_required_component_types()
42 downgrade_plugin_links_constraints() 59 downgrade_plugin_links_constraints()
43 60
@@ -107,3 +124,60 @@ def upgrade_release_required_component_types():
107 124
108def downgrade_release_required_component_types(): 125def downgrade_release_required_component_types():
109 op.drop_column('releases', 'required_component_types') 126 op.drop_column('releases', 'required_component_types')
127
128
129def upgrade_remove_vmware():
130 connection = op.get_bind()
131 op.drop_constraint(
132 'vmware_attributes_cluster_id_fkey',
133 'vmware_attributes',
134 type_='foreignkey'
135 )
136 op.drop_table('vmware_attributes')
137 op.drop_column('releases', 'vmware_attributes_metadata')
138 delete = sa.sql.text(
139 """DELETE FROM cluster_changes
140 WHERE name = 'vmware_attributes'""")
141 connection.execute(delete)
142 upgrade_enum(
143 "cluster_changes", # table
144 "name", # column
145 "possible_changes", # ENUM name
146 cluster_changes_old, # old options
147 cluster_changes_new # new options
148 )
149
150
151def downgrade_remove_vmware():
152 op.add_column(
153 'releases',
154 sa.Column('vmware_attributes_metadata', fields.JSON(), nullable=True))
155
156 op.create_table(
157 'vmware_attributes',
158 sa.Column('id', sa.Integer(), nullable=False),
159 sa.Column('cluster_id', sa.Integer()),
160 sa.Column('editable', fields.JSON()),
161 sa.ForeignKeyConstraint(['cluster_id'], ['clusters.id'], ),
162 sa.PrimaryKeyConstraint('id'))
163
164 upgrade_enum(
165 "cluster_changes", # table
166 "name", # column
167 "possible_changes", # ENUM name
168 cluster_changes_new, # new options
169 cluster_changes_old # old options
170 )
171
172 op.drop_constraint(
173 'vmware_attributes_cluster_id_fkey',
174 'vmware_attributes',
175 type_='foreignkey'
176 )
177
178 op.create_foreign_key(
179 'vmware_attributes_cluster_id_fkey',
180 'vmware_attributes', 'clusters',
181 ['cluster_id'], ['id'],
182 ondelete='CASCADE'
183 )
diff --git a/nailgun/nailgun/db/sqlalchemy/models/__init__.py b/nailgun/nailgun/db/sqlalchemy/models/__init__.py
index 78d1ce8..fc30084 100644
--- a/nailgun/nailgun/db/sqlalchemy/models/__init__.py
+++ b/nailgun/nailgun/db/sqlalchemy/models/__init__.py
@@ -33,7 +33,6 @@ from nailgun.db.sqlalchemy.models.deployment_graph import \
33from nailgun.db.sqlalchemy.models.cluster import Attributes 33from nailgun.db.sqlalchemy.models.cluster import Attributes
34from nailgun.db.sqlalchemy.models.cluster import Cluster 34from nailgun.db.sqlalchemy.models.cluster import Cluster
35from nailgun.db.sqlalchemy.models.cluster import ClusterChanges 35from nailgun.db.sqlalchemy.models.cluster import ClusterChanges
36from nailgun.db.sqlalchemy.models.cluster import VmwareAttributes
37 36
38from nailgun.db.sqlalchemy.models.release import Release 37from nailgun.db.sqlalchemy.models.release import Release
39 38
diff --git a/nailgun/nailgun/db/sqlalchemy/models/cluster.py b/nailgun/nailgun/db/sqlalchemy/models/cluster.py
index 06175dd..7c4ff96 100644
--- a/nailgun/nailgun/db/sqlalchemy/models/cluster.py
+++ b/nailgun/nailgun/db/sqlalchemy/models/cluster.py
@@ -93,8 +93,6 @@ class Cluster(Base):
93 backref="cluster", cascade="delete") 93 backref="cluster", cascade="delete")
94 changes_list = relationship("ClusterChanges", backref="cluster", 94 changes_list = relationship("ClusterChanges", backref="cluster",
95 cascade="delete") 95 cascade="delete")
96 vmware_attributes = relationship("VmwareAttributes", uselist=False,
97 backref="cluster", cascade="delete")
98 # We must keep all notifications even if cluster is removed. 96 # We must keep all notifications even if cluster is removed.
99 # It is because we want user to be able to see 97 # It is because we want user to be able to see
100 # the notification history so that is why we don't use 98 # the notification history so that is why we don't use
@@ -175,10 +173,3 @@ class Attributes(Base):
175 cluster_id = Column(Integer, ForeignKey('clusters.id', ondelete='CASCADE')) 173 cluster_id = Column(Integer, ForeignKey('clusters.id', ondelete='CASCADE'))
176 editable = Column(MutableDict.as_mutable(JSON)) 174 editable = Column(MutableDict.as_mutable(JSON))
177 generated = Column(MutableDict.as_mutable(JSON)) 175 generated = Column(MutableDict.as_mutable(JSON))
178
179
180class VmwareAttributes(Base):
181 __tablename__ = 'vmware_attributes'
182 id = Column(Integer, primary_key=True)
183 cluster_id = Column(Integer, ForeignKey('clusters.id', ondelete='CASCADE'))
184 editable = Column(MutableDict.as_mutable(JSON))
diff --git a/nailgun/nailgun/db/sqlalchemy/models/release.py b/nailgun/nailgun/db/sqlalchemy/models/release.py
index a069b61..740b836 100644
--- a/nailgun/nailgun/db/sqlalchemy/models/release.py
+++ b/nailgun/nailgun/db/sqlalchemy/models/release.py
@@ -59,8 +59,6 @@ class Release(Base):
59 MutableDict.as_mutable(JSON), server_default='{}', nullable=False) 59 MutableDict.as_mutable(JSON), server_default='{}', nullable=False)
60 network_roles_metadata = Column( 60 network_roles_metadata = Column(
61 MutableList.as_mutable(JSON), default=[], server_default='[]') 61 MutableList.as_mutable(JSON), default=[], server_default='[]')
62 vmware_attributes_metadata = Column(
63 MutableDict.as_mutable(JSON), default={})
64 components_metadata = Column( 62 components_metadata = Column(
65 MutableList.as_mutable(JSON), default=[], server_default='[]') 63 MutableList.as_mutable(JSON), default=[], server_default='[]')
66 required_component_types = Column(MutableList.as_mutable(JSON), default=[], 64 required_component_types = Column(MutableList.as_mutable(JSON), default=[],
diff --git a/nailgun/nailgun/fixtures/openstack.yaml b/nailgun/nailgun/fixtures/openstack.yaml
index af85a5f..b758edc 100644
--- a/nailgun/nailgun/fixtures/openstack.yaml
+++ b/nailgun/nailgun/fixtures/openstack.yaml
@@ -68,7 +68,6 @@
68 conflicts: 68 conflicts:
69 - controller 69 - controller
70 - cinder 70 - cinder
71 - cinder-vmware
72 - ceph-osd 71 - ceph-osd
73 restrictions: 72 restrictions:
74 - condition: "settings:storage.volumes_block_device.value == false" 73 - condition: "settings:storage.volumes_block_device.value == false"
@@ -77,19 +76,6 @@
77 message: "Ceph RBD cannot be used with Cinder Block Device" 76 message: "Ceph RBD cannot be used with Cinder Block Device"
78 tags: 77 tags:
79 - cinder-block-device 78 - cinder-block-device
80 cinder-vmware:
81 name: "Cinder Proxy to VMware Datastore"
82 description: "Cinder-VMware provides scheduling of block storage resources delivered over VMware vCenter. Block storage can be used for database storage, expandable file systems, or providing a server with access to raw block level devices."
83 weight: 40
84 group: "storage"
85 limits:
86 recommended: 1
87 restrictions:
88 - condition: "settings:common.use_vcenter.value == false"
89 action: "hide"
90 message: "VMware vCenter not enabled for cluster"
91 tags:
92 - cinder-vmware
93 ceph-osd: 79 ceph-osd:
94 name: "Ceph OSD" 80 name: "Ceph OSD"
95 description: "Ceph storage can be configured to provide storage for block volumes (Cinder), images (Glance) and ephemeral instance storage (Nova). It can also provide object storage through the S3 and Swift API (See settings to enable each)." 81 description: "Ceph storage can be configured to provide storage for block volumes (Cinder), images (Glance) and ephemeral instance storage (Nova). It can also provide object storage through the S3 and Swift API (See settings to enable each)."
@@ -150,27 +136,6 @@
150 message: "Advanced feature should be enabled in feature groups" 136 message: "Advanced feature should be enabled in feature groups"
151 tags: 137 tags:
152 - virt 138 - virt
153 compute-vmware:
154 name: "Compute VMware"
155 description: "A node that runs nova-compute with VCDriver, that manages ESXi computing resources via VMware vCenter."
156 weight: 90
157 group: "compute"
158 conflicts:
159 - controller
160 - compute
161 - cinder
162 - cinder-block-device
163 - ceph-osd
164 - mongo
165 - base-os
166 - virt
167 - ironic
168 restrictions:
169 - condition: "settings:common.use_vcenter.value == false"
170 action: "hide"
171 message: "VMware vCenter not enabled for cluster"
172 tags:
173 - compute-vmware
174 ironic: 139 ironic:
175 name: "Ironic" 140 name: "Ironic"
176 description: "Ironic conductor." 141 description: "Ironic conductor."
@@ -203,8 +168,6 @@
203 has_primary: false 168 has_primary: false
204 cinder-block-device: 169 cinder-block-device:
205 has_primary: false 170 has_primary: false
206 cinder-vmware:
207 has_primary: false
208 ceph-osd: 171 ceph-osd:
209 has_primary: false 172 has_primary: false
210 mongo: 173 mongo:
@@ -213,8 +176,6 @@
213 has_primary: false 176 has_primary: false
214 virt: 177 virt:
215 has_primary: false 178 has_primary: false
216 compute-vmware:
217 has_primary: false
218 ironic: 179 ironic:
219 has_primary: false 180 has_primary: false
220 181
@@ -629,8 +590,6 @@
629 cinder: 590 cinder:
630 - {allocate_size: "min", id: "os"} 591 - {allocate_size: "min", id: "os"}
631 - {allocate_size: "all", id: "cinder"} 592 - {allocate_size: "all", id: "cinder"}
632 cinder-vmware:
633 - {allocate_size: "min", id: "os"}
634 ceph-osd: 593 ceph-osd:
635 - {allocate_size: "min", id: "os"} 594 - {allocate_size: "min", id: "os"}
636 - {allocate_size: "min", id: "cephjournal"} 595 - {allocate_size: "min", id: "cephjournal"}
@@ -652,8 +611,6 @@
652 virt: 611 virt:
653 - {allocate_size: "min", id: "os"} 612 - {allocate_size: "min", id: "os"}
654 - {allocate_size: "all", id: "vm"} 613 - {allocate_size: "all", id: "vm"}
655 compute-vmware:
656 - {allocate_size: "min", id: "os"}
657 ironic: 614 ironic:
658 - {allocate_size: "min", id: "os"} 615 - {allocate_size: "min", id: "os"}
659 - {allocate_size: "min", id: "logs"} 616 - {allocate_size: "min", id: "logs"}
@@ -1088,10 +1045,6 @@
1088 description: "Uncheck this box if the public gateway will not be available or will not respond to ICMP requests to the deployed cluster. If unchecked, the controllers will not take public gateway availability into account as part of the cluster health. If the cluster will not have internet access, you will need to make sure to provide proper offline mirrors for the deployment to succeed." 1045 description: "Uncheck this box if the public gateway will not be available or will not respond to ICMP requests to the deployed cluster. If unchecked, the controllers will not take public gateway availability into account as part of the cluster health. If the cluster will not have internet access, you will need to make sure to provide proper offline mirrors for the deployment to succeed."
1089 weight: 50 1046 weight: 50
1090 type: "checkbox" 1047 type: "checkbox"
1091 use_vcenter:
1092 value: false
1093 weight: 30
1094 type: "hidden"
1095 libvirt_type: 1048 libvirt_type:
1096 value: "qemu" 1049 value: "qemu"
1097 values: 1050 values:
@@ -1502,19 +1455,6 @@
1502 description: "Configures Glance to use the Ceph RBD backend to store images. If enabled, this option will prevent Swift from installing." 1455 description: "Configures Glance to use the Ceph RBD backend to store images. If enabled, this option will prevent Swift from installing."
1503 weight: 30 1456 weight: 30
1504 type: "checkbox" 1457 type: "checkbox"
1505 restrictions:
1506 - "settings:storage.images_vcenter.value == true": "Only one Glance backend could be selected."
1507 images_vcenter:
1508 value: false
1509 label: "VMware vCenter/ESXi datastore for images (Glance)"
1510 description: "Configures Glance to use the vCenter/ESXi backend to store images. If enabled, this option will prevent Swift from installing."
1511 weight: 35
1512 type: "checkbox"
1513 restrictions:
1514 - condition: "settings:common.use_vcenter.value != true"
1515 action: "hide"
1516 - condition: "settings:storage.images_ceph.value == true"
1517 message: "Only one Glance backend could be selected."
1518 ephemeral_ceph: 1458 ephemeral_ceph:
1519 value: false 1459 value: false
1520 label: "Ceph RBD for ephemeral volumes (Nova)" 1460 label: "Ceph RBD for ephemeral volumes (Nova)"
@@ -1681,182 +1621,6 @@
1681 modules: "rsync://{settings.MASTER_IP}:/puppet/{cluster.release.version}/modules/" 1621 modules: "rsync://{settings.MASTER_IP}:/puppet/{cluster.release.version}/modules/"
1682 deployed_before: 1622 deployed_before:
1683 value: false 1623 value: false
1684 vmware_attributes_metadata:
1685 editable:
1686 metadata:
1687 -
1688 name: "availability_zones"
1689 type: "array"
1690 restrictions:
1691 - condition: "settings:common.use_vcenter.value == false"
1692 message: "VMware vCenter not enabled for cluster"
1693 fields:
1694 -
1695 name: "az_name"
1696 type: "text"
1697 label: "Availability zone"
1698 description: "Availability zone name"
1699 regex:
1700 source: &availability_zone_blacklist '^(?!nova$)\w+$'
1701 error: "Invalid availability zone name"
1702 -
1703 name: "vcenter_host"
1704 type: "text"
1705 label: "vCenter host"
1706 description: "vCenter host or IP"
1707 regex:
1708 source: *ipv4_or_hostname_regex
1709 error: "Invalid vCenter host"
1710 -
1711 name: "vcenter_username"
1712 type: "text"
1713 label: "vCenter username"
1714 description: "vCenter username"
1715 regex:
1716 source: *non_empty_string
1717 error: "Empty vCenter username"
1718 -
1719 name: "vcenter_password"
1720 type: "password"
1721 label: "vCenter password"
1722 description: "vCenter password"
1723 regex:
1724 source: *non_empty_string
1725 error: "Empty vCenter password"
1726 -
1727 name: "vcenter_security_disabled"
1728 type: "checkbox"
1729 label: "Bypass vCenter certificate verification"
1730 -
1731 name: "vcenter_ca_file"
1732 type: "file"
1733 label: "CA file"
1734 description: "File containing the trusted CA bundle that emitted vCenter server certificate. Even if CA bundle is not uploaded, certificate verification is turned on."
1735 restrictions:
1736 - condition: "current_vcenter:vcenter_security_disabled == true"
1737 message: "Bypass vCenter certificate verification should be disabled."
1738 -
1739 name: "nova_computes"
1740 type: "array"
1741 editable_for_deployed: true
1742 fields:
1743 -
1744 name: "vsphere_cluster"
1745 type: "text"
1746 label: "vSphere cluster"
1747 description: "vSphere cluster"
1748 regex:
1749 source: *non_empty_string
1750 error: "Invalid vSphere cluster"
1751 -
1752 name: "service_name"
1753 type: "text"
1754 label: "Service name"
1755 description: "Service name"
1756 regex:
1757 source: '^\w[\w\-]+$'
1758 error: "Invalid service name"
1759 -
1760 name: "datastore_regex"
1761 type: "text"
1762 label: "Datastore regex"
1763 description: "Datastore regex"
1764 regex:
1765 source: *non_empty_string
1766 error: "Invalid datastore regex"
1767 -
1768 name: "target_node"
1769 type: "select"
1770 label: "Target node"
1771 description: "Target node for nova-compute service"
1772 -
1773 name: "glance"
1774 type: "object"
1775 restrictions:
1776 - condition: "settings:storage.images_vcenter.value == false or settings:common.use_vcenter.value == false"
1777 message: "VMware vCenter datastore for images is not enabled in Settings tab"
1778 fields:
1779 -
1780 name: "vcenter_host"
1781 type: "text"
1782 label: "vCenter host"
1783 description: "vCenter host or IP"
1784 regex:
1785 source: *ipv4_or_hostname_regex
1786 error: "Invalid vCenter host"
1787 -
1788 name: "vcenter_username"
1789 type: "text"
1790 label: "vCenter username"
1791 description: "vCenter username"
1792 regex:
1793 source: *non_empty_string
1794 error: "Empty vCenter username"
1795 -
1796 name: "vcenter_password"
1797 type: "password"
1798 label: "vCenter password"
1799 description: "vCenter password"
1800 regex:
1801 source: *non_empty_string
1802 error: "Empty vCenter password"
1803 -
1804 name: "datacenter"
1805 type: "text"
1806 label: "Datacenter"
1807 description: "Datacenter"
1808 regex:
1809 source: *non_empty_string
1810 error: "Invalid datacenter"
1811 -
1812 name: "datastore"
1813 type: "text"
1814 label: "Datastore"
1815 description: "Datastore"
1816 regex:
1817 source: *non_empty_string
1818 error: "Invalid datastore"
1819 -
1820 name: "vcenter_security_disabled"
1821 type: "checkbox"
1822 label: "Bypass vCenter certificate verification"
1823 -
1824 name: "ca_file"
1825 type: "file"
1826 label: "CA file"
1827 description: "File containing the trusted CA bundle that emitted vCenter server certificate. Even if CA bundle is not uploaded, certificate verification is turned on."
1828 restrictions:
1829 - condition: "glance:vcenter_security_disabled == true"
1830 message: "Bypass vCenter certificate verification should be disabled."
1831 value:
1832 availability_zones:
1833 -
1834 az_name: "vcenter"
1835 vcenter_host: ""
1836 vcenter_username: ""
1837 vcenter_password: ""
1838 vcenter_security_disabled: true
1839 vcenter_ca_file: {}
1840 nova_computes:
1841 -
1842 vsphere_cluster: ""
1843 service_name: ""
1844 datastore_regex: ""
1845 target_node:
1846 options:
1847 - id: "controllers"
1848 label: "controllers"
1849 current:
1850 id: "controllers"
1851 label: "controllers"
1852 glance:
1853 vcenter_host: ""
1854 vcenter_username: ""
1855 vcenter_password: ""
1856 datacenter: ""
1857 datastore: ""
1858 vcenter_security_disabled: true
1859 ca_file: {}
1860 components_metadata: 1624 components_metadata:
1861 - name: hypervisor:qemu 1625 - name: hypervisor:qemu
1862 default: true 1626 default: true
@@ -1866,26 +1630,7 @@
1866 label: "dialog.create_cluster_wizard.compute.qemu" 1630 label: "dialog.create_cluster_wizard.compute.qemu"
1867 description: "dialog.create_cluster_wizard.compute.qemu_description" 1631 description: "dialog.create_cluster_wizard.compute.qemu_description"
1868 compatible: 1632 compatible:
1869 - name: hypervisor:vmware 1633 - name: hypervisor:*
1870 - name: hypervisor:vmware
1871 weight: 15
1872 bind:
1873 - "settings:common.use_vcenter.value"
1874 label: "dialog.create_cluster_wizard.compute.vcenter"
1875 description: "dialog.create_cluster_wizard.compute.vcenter_description"
1876 compatible:
1877 - name: hypervisor:qemu
1878 requires:
1879 - one_of:
1880 items:
1881 - hypervisor:qemu
1882 message: "dialog.create_cluster_wizard.compute.vcenter_warning"
1883 - one_of:
1884 items:
1885 - network:neutron:ml2:dvs
1886 - network:neutron:ml2:nsx
1887 message: "dialog.create_cluster_wizard.compute.vcenter_requires_network_backend"
1888 message_invalid: "dialog.create_cluster_wizard.compute.vcenter_requires_network_plugins"
1889 - name: network:neutron:core:ml2 1634 - name: network:neutron:core:ml2
1890 default: true 1635 default: true
1891 weight: 1000 1636 weight: 1000
@@ -1908,7 +1653,6 @@
1908 compatible: 1653 compatible:
1909 - name: network:neutron:core:ml2 1654 - name: network:neutron:core:ml2
1910 - name: hypervisor:qemu 1655 - name: hypervisor:qemu
1911 - name: hypervisor:vmware
1912 requires: 1656 requires:
1913 - one_of: 1657 - one_of:
1914 items: 1658 items:
@@ -1926,8 +1670,6 @@
1926 incompatible: 1670 incompatible:
1927 - name: network:neutron:ml2:vlan 1671 - name: network:neutron:ml2:vlan
1928 message: "dialog.create_cluster_wizard.network.vlan_tun_alert" 1672 message: "dialog.create_cluster_wizard.network.vlan_tun_alert"
1929 - name: hypervisor:vmware
1930 message: "dialog.create_cluster_wizard.network.hypervisor_alert"
1931 - name: additional_service:ironic 1673 - name: additional_service:ironic
1932 message: "dialog.create_cluster_wizard.additional.ironic_network_mode_alert" 1674 message: "dialog.create_cluster_wizard.additional.ironic_network_mode_alert"
1933 requires: 1675 requires:
@@ -1943,7 +1685,6 @@
1943 - "settings:storage.volumes_lvm.value" 1685 - "settings:storage.volumes_lvm.value"
1944 compatible: 1686 compatible:
1945 - name: hypervisor:qemu 1687 - name: hypervisor:qemu
1946 - name: hypervisor:vmware
1947 - name: network:neutron:core:ml2 1688 - name: network:neutron:core:ml2
1948 - name: network:neutron:ml2:vlan 1689 - name: network:neutron:ml2:vlan
1949 - name: network:neutron:ml2:tun 1690 - name: network:neutron:ml2:tun
@@ -1959,7 +1700,6 @@
1959 - "settings:storage.volumes_lvm.value": false 1700 - "settings:storage.volumes_lvm.value": false
1960 compatible: 1701 compatible:
1961 - name: hypervisor:qemu 1702 - name: hypervisor:qemu
1962 - name: hypervisor:vmware
1963 - name: network:neutron:core:ml2 1703 - name: network:neutron:core:ml2
1964 - name: network:neutron:ml2:vlan 1704 - name: network:neutron:ml2:vlan
1965 - name: network:neutron:ml2:tun 1705 - name: network:neutron:ml2:tun
@@ -1977,7 +1717,6 @@
1977 - "settings:storage.objects_ceph.value" 1717 - "settings:storage.objects_ceph.value"
1978 compatible: 1718 compatible:
1979 - name: hypervisor:qemu 1719 - name: hypervisor:qemu
1980 - name: hypervisor:vmware
1981 - name: network:neutron:core:ml2 1720 - name: network:neutron:core:ml2
1982 - name: network:neutron:ml2:vlan 1721 - name: network:neutron:ml2:vlan
1983 - name: network:neutron:ml2:tun 1722 - name: network:neutron:ml2:tun
@@ -1993,7 +1732,6 @@
1993 - "settings:storage.ephemeral_ceph.value" 1732 - "settings:storage.ephemeral_ceph.value"
1994 compatible: 1733 compatible:
1995 - name: hypervisor:qemu 1734 - name: hypervisor:qemu
1996 - name: hypervisor:vmware
1997 - name: network:neutron:core:ml2 1735 - name: network:neutron:core:ml2
1998 - name: network:neutron:ml2:vlan 1736 - name: network:neutron:ml2:vlan
1999 - name: network:neutron:ml2:tun 1737 - name: network:neutron:ml2:tun
@@ -2009,7 +1747,6 @@
2009 - "settings:storage.images_ceph.value" 1747 - "settings:storage.images_ceph.value"
2010 compatible: 1748 compatible:
2011 - name: hypervisor:qemu 1749 - name: hypervisor:qemu
2012 - name: hypervisor:vmware
2013 - name: network:neutron:core:ml2 1750 - name: network:neutron:core:ml2
2014 - name: network:neutron:ml2:vlan 1751 - name: network:neutron:ml2:vlan
2015 - name: network:neutron:ml2:tun 1752 - name: network:neutron:ml2:tun
@@ -2025,7 +1762,6 @@
2025 description: "dialog.create_cluster_wizard.additional.install_sahara_description" 1762 description: "dialog.create_cluster_wizard.additional.install_sahara_description"
2026 compatible: 1763 compatible:
2027 - name: hypervisor:qemu 1764 - name: hypervisor:qemu
2028 - name: hypervisor:vmware
2029 - name: network:neutron:core:ml2 1765 - name: network:neutron:core:ml2
2030 - name: network:neutron:ml2:vlan 1766 - name: network:neutron:ml2:vlan
2031 - name: network:neutron:ml2:tun 1767 - name: network:neutron:ml2:tun
@@ -2046,7 +1782,6 @@
2046 description: "dialog.create_cluster_wizard.additional.install_murano_description" 1782 description: "dialog.create_cluster_wizard.additional.install_murano_description"
2047 compatible: 1783 compatible:
2048 - name: hypervisor:qemu 1784 - name: hypervisor:qemu
2049 - name: hypervisor:vmware
2050 - name: network:neutron:core:ml2 1785 - name: network:neutron:core:ml2
2051 - name: network:neutron:ml2:vlan 1786 - name: network:neutron:ml2:vlan
2052 - name: network:neutron:ml2:tun 1787 - name: network:neutron:ml2:tun
@@ -2066,7 +1801,6 @@
2066 description: "dialog.create_cluster_wizard.additional.install_ceilometer_description" 1801 description: "dialog.create_cluster_wizard.additional.install_ceilometer_description"
2067 compatible: 1802 compatible:
2068 - name: hypervisor:qemu 1803 - name: hypervisor:qemu
2069 - name: hypervisor:vmware
2070 - name: network:neutron:core:ml2 1804 - name: network:neutron:core:ml2
2071 - name: network:neutron:ml2:vlan 1805 - name: network:neutron:ml2:vlan
2072 - name: network:neutron:ml2:tun 1806 - name: network:neutron:ml2:tun
diff --git a/nailgun/nailgun/fixtures/sample_plugins.json b/nailgun/nailgun/fixtures/sample_plugins.json
index 65bae3e..95d52d2 100644
--- a/nailgun/nailgun/fixtures/sample_plugins.json
+++ b/nailgun/nailgun/fixtures/sample_plugins.json
@@ -159,12 +159,6 @@
159 "package_version": "2.0.0", 159 "package_version": "2.0.0",
160 "attributes_metadata": { 160 "attributes_metadata": {
161 "metadata": { 161 "metadata": {
162 "restrictions": [
163 {
164 "condition": "settings:common.use_vcenter.value == true",
165 "action": "hide"
166 }
167 ]
168 }, 162 },
169 "zabbix_text_1": { 163 "zabbix_text_1": {
170 "value": "value 1.1", 164 "value": "value 1.1",
diff --git a/nailgun/nailgun/fixtures/vmware_attributes.json b/nailgun/nailgun/fixtures/vmware_attributes.json
deleted file mode 100644
index 46f5906..0000000
--- a/nailgun/nailgun/fixtures/vmware_attributes.json
+++ /dev/null
@@ -1,245 +0,0 @@
1[{
2 "pk": 1,
3 "editable": {
4 "metadata": [
5 {
6 "fields": [
7 {
8 "type": "text",
9 "description": "Availability zone name",
10 "name": "az_name",
11 "label": "AZ name"
12 },
13 {
14 "type": "text",
15 "description": "vCenter host or IP",
16 "name": "vcenter_host",
17 "label": "vCenter host"
18 },
19 {
20 "type": "text",
21 "description": "vCenter username",
22 "name": "vcenter_username",
23 "label": "vCenter username"
24 },
25 {
26 "type": "password",
27 "description": "vCenter password",
28 "name": "vcenter_password",
29 "label": "vCenter password"
30 },
31 {
32 "type": "checkbox",
33 "name": "vcenter_security_disabled",
34 "label": "Bypass vCenter certificate verification"
35 },
36 {
37 "type": "file",
38 "description": "File containing the trusted CA bundle that emitted vCenter server certificate. Even if CA bundle is not uploaded, certificate verification is turned on.",
39 "name": "vcenter_ca_file",
40 "label": "CA file",
41 "restrictions": [
42 {
43 "condition": "current_vcenter:vcenter_security_disabled == true",
44 "message": "Bypass vCenter certificate verification should be disabled."
45 }
46 ]
47 },
48 {
49 "fields": [
50 {
51 "type": "text",
52 "description": "vSphere Cluster",
53 "name": "vsphere_cluster",
54 "label": "vSphere Cluster",
55 "regex": {
56 "source": "\\S",
57 "error": "Empty cluster"
58 }
59 },
60 {
61 "type": "text",
62 "description": "Service name",
63 "name": "service_name",
64 "label": "Service name"
65 },
66 {
67 "type": "text",
68 "description": "Datastore regex",
69 "name": "datastore_regex",
70 "label": "Datastore regex"
71 },
72 {
73 "type": "select",
74 "description": "Target node for nova-compute service",
75 "name": "target_node",
76 "label": "Target node"
77 }
78 ],
79 "type": "array",
80 "name": "nova_computes"
81 }
82 ],
83 "type": "array",
84 "name": "availability_zones"
85 },
86 {
87 "fields": [
88 {
89 "type": "text",
90 "description": "VLAN interface",
91 "name": "esxi_vlan_interface",
92 "label": "VLAN interface"
93 }
94 ],
95 "type": "object",
96 "name": "network"
97 },
98 {
99 "fields": [
100 {
101 "type": "text",
102 "description": "VCenter host or IP",
103 "name": "vcenter_host",
104 "label": "VCenter Host",
105 "regex": {
106 "source": "\\S",
107 "error": "Empty host"
108 }
109 },
110 {
111 "type": "text",
112 "description": "vCenter username",
113 "name": "vcenter_username",
114 "label": "vCenter username",
115 "regex": {
116 "source": "\\S",
117 "error": "Empty username"
118 }
119 },
120 {
121 "type": "password",
122 "description": "vCenter password",
123 "name": "vcenter_password",
124 "label": "vCenter password",
125 "regex": {
126 "source": "\\S",
127 "error": "Empty password"
128 }
129 },
130 {
131 "type": "text",
132 "description": "Datacenter",
133 "name": "datacenter",
134 "label": "Datacenter",
135 "regex": {
136 "source": "\\S",
137 "error": "Empty datacenter"
138 }
139 },
140 {
141 "type": "text",
142 "description": "Datastore",
143 "name": "datastore",
144 "label": "Datastore",
145 "regex": {
146 "source": "\\S",
147 "error": "Empty datastore"
148 }
149 },
150 {
151 "type": "checkbox",
152 "name": "vcenter_security_disabled",
153 "label": "Bypass vCenter certificate verification"
154 },
155 {
156 "type": "file",
157 "description": "File containing the trusted CA bundle that emitted vCenter server certificate. Even if CA bundle is not uploaded, certificate verification is turned on.",
158 "name": "ca_file",
159 "label": "CA file",
160 "restrictions": [
161 {
162 "condition": "glance:vcenter_security_disabled == true",
163 "message": "Bypass vCenter certificate verification should be disabled."
164 }
165 ]
166 }
167 ],
168 "type": "object",
169 "name": "glance",
170 "restrictions": [
171 {
172 "action": "hide",
173 "condition": "settings:storage.images_vcenter.value == false or settings:common.use_vcenter.value == false"
174 }
175 ]
176 }
177 ],
178 "value": {
179 "availability_zones": [
180 {
181 "az_name": "Zone 1",
182 "vcenter_host": "1.2.3.4",
183 "vcenter_username": "admin",
184 "vcenter_password": "secret",
185 "vcenter_security_disabled": "true",
186 "vcenter_ca_file": "file_blob",
187 "nova_computes": [
188 {
189 "vsphere_cluster": "cluster1",
190 "service_name": "Compute 1",
191 "datastore_regex": "",
192 "target_node": {
193 "current": {
194 "id": "test_target_node"
195 }
196 }
197 },
198 {
199 "vsphere_cluster": "cluster2",
200 "service_name": "Compute 3",
201 "datastore_regex": "",
202 "target_node": {
203 "current": {
204 "id": "test_target_node"
205 }
206 }
207 }
208 ]
209 },
210 {
211 "az_name": "Zone 2",
212 "vcenter_host": "1.2.3.6",
213 "vcenter_username": "user$",
214 "vcenter_password": "pass$word",
215 "vcenter_security_disabled": "true",
216 "vcenter_ca_file": "file_blob",
217 "nova_computes": [
218 {
219 "vsphere_cluster": "cluster1",
220 "service_name": "Compute 4",
221 "datastore_regex": "^openstack-[0-9]$"
222 },
223 {
224 "vsphere_cluster": "",
225 "service_name": "Compute 7",
226 "datastore_regex": ""
227 }
228 ]
229 }
230 ],
231 "glance": {
232 "vcenter_host": "1.2.3.4",
233 "vcenter_username": "admin",
234 "vcenter_password": "secret",
235 "datacenter": "test_datacenter",
236 "datastore": "test_datastore",
237 "vcenter_security_disabled": "true",
238 "ca_file": "file_blob"
239 },
240 "network": {
241 "esxi_vlan_interface": "eth0"
242 }
243 }
244 }
245}]
diff --git a/nailgun/nailgun/objects/__init__.py b/nailgun/nailgun/objects/__init__.py
index 69d6f80..2e41353 100644
--- a/nailgun/nailgun/objects/__init__.py
+++ b/nailgun/nailgun/objects/__init__.py
@@ -34,7 +34,6 @@ from nailgun.objects.release import ReleaseCollection
34from nailgun.objects.cluster import Attributes 34from nailgun.objects.cluster import Attributes
35from nailgun.objects.cluster import Cluster 35from nailgun.objects.cluster import Cluster
36from nailgun.objects.cluster import ClusterCollection 36from nailgun.objects.cluster import ClusterCollection
37from nailgun.objects.cluster import VmwareAttributes
38 37
39from nailgun.objects.task import Task 38from nailgun.objects.task import Task
40from nailgun.objects.task import TaskCollection 39from nailgun.objects.task import TaskCollection
diff --git a/nailgun/nailgun/objects/cluster.py b/nailgun/nailgun/objects/cluster.py
index 17e3ca6..37dd80e 100644
--- a/nailgun/nailgun/objects/cluster.py
+++ b/nailgun/nailgun/objects/cluster.py
@@ -176,7 +176,6 @@ class Cluster(NailgunObject):
176 cls.create_default_group(cluster) 176 cls.create_default_group(cluster)
177 177
178 cls.create_attributes(cluster, enabled_editable_attributes) 178 cls.create_attributes(cluster, enabled_editable_attributes)
179 cls.create_vmware_attributes(cluster)
180 cls.create_default_extensions(cluster) 179 cls.create_default_extensions(cluster)
181 180
182 # default graph should be created in any case 181 # default graph should be created in any case
@@ -184,8 +183,6 @@ class Cluster(NailgunObject):
184 183
185 cls.add_pending_changes( 184 cls.add_pending_changes(
186 cluster, consts.CLUSTER_CHANGES.attributes) 185 cluster, consts.CLUSTER_CHANGES.attributes)
187 cls.add_pending_changes(
188 cluster, consts.CLUSTER_CHANGES.vmware_attributes)
189 186
190 ClusterPlugin.add_compatible_plugins(cluster) 187 ClusterPlugin.add_compatible_plugins(cluster)
191 PluginManager.enable_plugins_by_components(cluster) 188 PluginManager.enable_plugins_by_components(cluster)
@@ -1330,20 +1327,6 @@ class Cluster(NailgunObject):
1330 return volumes_metadata 1327 return volumes_metadata
1331 1328
1332 @classmethod 1329 @classmethod
1333 def create_vmware_attributes(cls, instance):
1334 """Store VmwareAttributes instance into DB."""
1335 vmware_metadata = instance.release.vmware_attributes_metadata
1336 if vmware_metadata:
1337 return VmwareAttributes.create(
1338 {
1339 "editable": vmware_metadata.get("editable"),
1340 "cluster_id": instance.id
1341 }
1342 )
1343
1344 return None
1345
1346 @classmethod
1347 def get_create_data(cls, instance): 1330 def get_create_data(cls, instance):
1348 """Return common parameters cluster was created with. 1331 """Return common parameters cluster was created with.
1349 1332
@@ -1363,52 +1346,6 @@ class Cluster(NailgunObject):
1363 get_network_config_create_data(instance)) 1346 get_network_config_create_data(instance))
1364 return data 1347 return data
1365 1348
1366 @classmethod
1367 def get_vmware_attributes(cls, instance):
1368 """Get VmwareAttributes instance from DB.
1369
1370 Now we have relation with cluster 1:1.
1371 """
1372 return db().query(models.VmwareAttributes).filter(
1373 models.VmwareAttributes.cluster_id == instance.id
1374 ).first()
1375
1376 @classmethod
1377 def get_default_vmware_attributes(cls, instance):
1378 """Get metadata from release with empty value section."""
1379 editable = instance.release.vmware_attributes_metadata.get("editable")
1380 editable = traverse(
1381 editable,
1382 formatter_context={'cluster': instance, 'settings': settings},
1383 keywords={'generator': AttributesGenerator.evaluate}
1384 )
1385 return editable
1386
1387 @classmethod
1388 def update_vmware_attributes(cls, instance, data):
1389 """Update Vmware attributes.
1390
1391 Actually we allways update only value section in editable.
1392 """
1393 metadata = instance.vmware_attributes.editable['metadata']
1394 value = data.get('editable', {}).get('value')
1395 vmware_attr = {
1396 'metadata': metadata,
1397 'value': value
1398 }
1399 setattr(instance.vmware_attributes, 'editable', vmware_attr)
1400 cls.add_pending_changes(instance, "vmware_attributes")
1401 db().flush()
1402 vmware_attr.pop('metadata')
1403
1404 return vmware_attr
1405
1406 @classmethod
1407 def is_vmware_enabled(cls, instance):
1408 """Check if current cluster supports vmware configuration."""
1409 attributes = cls.get_editable_attributes(instance)
1410 return attributes.get('common', {}).get('use_vcenter', {}).get('value')
1411
1412 @staticmethod 1349 @staticmethod
1413 def adjust_nodes_lists_on_controller_removing(instance, nodes_to_delete, 1350 def adjust_nodes_lists_on_controller_removing(instance, nodes_to_delete,
1414 nodes_to_deploy): 1351 nodes_to_deploy):
@@ -1583,31 +1520,6 @@ class Cluster(NailgunObject):
1583 ) 1520 )
1584 1521
1585 @classmethod 1522 @classmethod
1586 def has_compute_vmware_changes(cls, instance):
1587 """Checks if any 'compute-vmware' nodes are waiting for deployment.
1588
1589 :param instance: cluster for checking
1590 :type instance: nailgun.db.sqlalchemy.models.Cluster instance
1591 """
1592 compute_vmware_nodes_query = db().query(models.Node).filter_by(
1593 cluster_id=instance.id
1594 ).filter(sa.or_(
1595 sa.and_(models.Node.roles.any('compute-vmware'),
1596 models.Node.pending_deletion),
1597 models.Node.pending_roles.any('compute-vmware')
1598 ))
1599 return db().query(compute_vmware_nodes_query.exists()).scalar()
1600
1601 @classmethod
1602 def get_operational_vmware_compute_nodes(cls, instance):
1603 return db().query(models.Node).filter_by(
1604 cluster_id=instance.id
1605 ).filter(
1606 models.Node.roles.any('compute-vmware'),
1607 sa.not_(models.Node.pending_deletion)
1608 ).all()
1609
1610 @classmethod
1611 def is_task_deploy_enabled(cls, instance): 1523 def is_task_deploy_enabled(cls, instance):
1612 """Tests that task based deploy is enabled. 1524 """Tests that task based deploy is enabled.
1613 1525
@@ -1708,26 +1620,3 @@ class ClusterCollection(NailgunCollection):
1708 1620
1709 #: Single Cluster object class 1621 #: Single Cluster object class
1710 single = Cluster 1622 single = Cluster
1711
1712
1713class VmwareAttributes(NailgunObject):
1714 model = models.VmwareAttributes
1715
1716 @staticmethod
1717 def get_nova_computes_attrs(attributes):
1718 return attributes.get('value', {}).get(
1719 'availability_zones', [{}])[0].get('nova_computes', [])
1720
1721 @classmethod
1722 def get_nova_computes_target_nodes(cls, instance):
1723 """Get data of targets node for all nova computes.
1724
1725 :param instance: nailgun.db.sqlalchemy.models.Cluster instance
1726 :returns: list of dicts that represents nova compute targets
1727 """
1728 nova_compute_target_nodes = []
1729 for nova_compute in cls.get_nova_computes_attrs(instance.editable):
1730 target = nova_compute['target_node']['current']
1731 if target['id'] != 'controllers':
1732 nova_compute_target_nodes.append(target)
1733 return nova_compute_target_nodes
diff --git a/nailgun/nailgun/objects/serializers/release.py b/nailgun/nailgun/objects/serializers/release.py
index c10c0de..817b72b 100644
--- a/nailgun/nailgun/objects/serializers/release.py
+++ b/nailgun/nailgun/objects/serializers/release.py
@@ -31,7 +31,6 @@ class ReleaseSerializer(BasicSerializer):
31 "tags_metadata", 31 "tags_metadata",
32 "state", 32 "state",
33 "attributes_metadata", 33 "attributes_metadata",
34 "vmware_attributes_metadata",
35 "components_metadata" 34 "components_metadata"
36 ) 35 )
37 36
diff --git a/nailgun/nailgun/orchestrator/base_serializers.py b/nailgun/nailgun/orchestrator/base_serializers.py
index bd22378..61060c4 100644
--- a/nailgun/nailgun/orchestrator/base_serializers.py
+++ b/nailgun/nailgun/orchestrator/base_serializers.py
@@ -146,105 +146,3 @@ class MuranoMetadataSerializerMixin(object):
146 test_vm_image['properties']['murano_image_info'] = \ 146 test_vm_image['properties']['murano_image_info'] = \
147 """'{"title": "Murano Demo", "type": "cirros.demo"}'""" 147 """'{"title": "Murano Demo", "type": "cirros.demo"}'"""
148 return {'test_vm_image': test_vm_image} 148 return {'test_vm_image': test_vm_image}
149
150
151class VmwareDeploymentSerializerMixin(object):
152
153 def generate_vmware_data(self, node):
154 """Extend serialize data with vmware attributes"""
155 vmware_data = {}
156 use_vcenter = node.cluster.attributes.editable.get('common', {}) \
157 .get('use_vcenter', {}).get('value')
158
159 if use_vcenter:
160 compute_instances = []
161 cinder_instances = []
162
163 vmware_attributes = node.cluster.vmware_attributes.editable \
164 .get('value', {})
165 availability_zones = vmware_attributes \
166 .get('availability_zones', {})
167 glance_instance = vmware_attributes.get('glance', {})
168 network = vmware_attributes.get('network', {})
169
170 for zone in availability_zones:
171
172 vc_user = self.escape_dollar(zone.get('vcenter_username', ''))
173 vc_password = self.escape_dollar(zone.get('vcenter_password',
174 ''))
175
176 for compute in zone.get('nova_computes', {}):
177 datastore_regex = \
178 self.escape_dollar(compute.get('datastore_regex', ''))
179
180 compute_item = {
181 'availability_zone_name': zone.get('az_name', ''),
182 'vc_host': zone.get('vcenter_host', ''),
183 'vc_user': vc_user,
184 'vc_password': vc_password,
185 'vc_insecure': zone.get('vcenter_security_disabled',
186 ''),
187 'vc_ca_file': zone.get('vcenter_ca_file', ''),
188 'service_name': compute.get('service_name', ''),
189 'vc_cluster': compute.get('vsphere_cluster', ''),
190 'datastore_regex': datastore_regex,
191 'target_node': compute.get('target_node', {}).get(
192 'current', {}).get('id', 'controllers')
193 }
194
195 compute_instances.append(compute_item)
196
197 cinder_item = {
198 'availability_zone_name': zone.get('az_name', ''),
199 'vc_host': zone.get('vcenter_host', ''),
200 'vc_user': vc_user,
201 'vc_password': vc_password,
202 'vc_insecure': zone.get('vcenter_security_disabled', ''),
203 'vc_ca_file': zone.get('vcenter_ca_file', '')
204 }
205 cinder_instances.append(cinder_item)
206
207 vmware_data['use_vcenter'] = True
208
209 if compute_instances:
210 vmware_data['vcenter'] = {
211 'esxi_vlan_interface':
212 network.get('esxi_vlan_interface', ''),
213 'computes': compute_instances
214 }
215
216 if cinder_instances:
217 vmware_data['cinder'] = {
218 'instances': cinder_instances
219 }
220
221 if glance_instance:
222 glance_username = \
223 self.escape_dollar(glance_instance
224 .get('vcenter_username', ''))
225 glance_password = \
226 self.escape_dollar(glance_instance
227 .get('vcenter_password', ''))
228
229 vmware_data['glance'] = {
230 'vc_host': glance_instance.get('vcenter_host', ''),
231 'vc_user': glance_username,
232 'vc_password': glance_password,
233 'vc_datacenter': glance_instance.get('datacenter', ''),
234 'vc_datastore': glance_instance.get('datastore', ''),
235 'vc_insecure': glance_instance.get(
236 'vcenter_security_disabled', ''),
237 'vc_ca_file': glance_instance.get('ca_file', '')
238 }
239
240 return vmware_data
241
242 @staticmethod
243 def escape_dollar(data):
244 """Escape dollar symbol
245
246 In order to disable variable interpolation in
247 values that we write to configuration files during
248 deployment we must replace all $ (dollar sign) occurrences.
249 """
250 return data.replace('$', '$$')
diff --git a/nailgun/nailgun/orchestrator/deployment_serializers.py b/nailgun/nailgun/orchestrator/deployment_serializers.py
index 5f0a473..d9bf3b6 100644
--- a/nailgun/nailgun/orchestrator/deployment_serializers.py
+++ b/nailgun/nailgun/orchestrator/deployment_serializers.py
@@ -16,7 +16,6 @@
16 16
17"""Deployment serializers for orchestrator""" 17"""Deployment serializers for orchestrator"""
18 18
19from copy import deepcopy
20from distutils.version import StrictVersion 19from distutils.version import StrictVersion
21 20
22import six 21import six
@@ -33,8 +32,6 @@ from nailgun.utils.resolvers import NameMatchingPolicy
33from nailgun.utils.resolvers import TagResolver 32from nailgun.utils.resolvers import TagResolver
34 33
35from nailgun.orchestrator.base_serializers import MuranoMetadataSerializerMixin 34from nailgun.orchestrator.base_serializers import MuranoMetadataSerializerMixin
36from nailgun.orchestrator.base_serializers import \
37 VmwareDeploymentSerializerMixin
38from nailgun.orchestrator.provisioning_serializers import \ 35from nailgun.orchestrator.provisioning_serializers import \
39 ProvisionLCMSerializer 36 ProvisionLCMSerializer
40 37
@@ -266,18 +263,6 @@ class DeploymentMultinodeSerializer(object):
266 263
267 properties_data = {} 264 properties_data = {}
268 265
269 # Alternate VMWare specific values.
270 if c_attrs['editable']['common']['libvirt_type']['value'] == 'vcenter':
271 image_data.update({
272 'disk_format': 'vmdk',
273 'img_path': '{0}cirros-i386-disk.vmdk'.format(img_dir),
274 })
275 properties_data = {
276 'vmware_disktype': 'sparse',
277 'vmware_adaptertype': 'lsiLogic',
278 'hypervisor_type': 'vmware'
279 }
280
281 # NOTE(aschultz): properties was added as part of N and should be 266 # NOTE(aschultz): properties was added as part of N and should be
282 # used infavor of glance_properties 267 # used infavor of glance_properties
283 image_data['glance_properties'] = self.generate_properties_arguments( 268 image_data['glance_properties'] = self.generate_properties_arguments(
@@ -426,8 +411,7 @@ class DeploymentHASerializer60(DeploymentHASerializer50):
426 neutron_serializers.NeutronNetworkDeploymentSerializer60 411 neutron_serializers.NeutronNetworkDeploymentSerializer60
427 412
428 413
429class DeploymentMultinodeSerializer61(DeploymentMultinodeSerializer, 414class DeploymentMultinodeSerializer61(DeploymentMultinodeSerializer):
430 VmwareDeploymentSerializerMixin):
431 415
432 nova_network_serializer = \ 416 nova_network_serializer = \
433 nova_serializers.NovaNetworkDeploymentSerializer61 417 nova_serializers.NovaNetworkDeploymentSerializer61
@@ -438,7 +422,6 @@ class DeploymentMultinodeSerializer61(DeploymentMultinodeSerializer,
438 base = super(DeploymentMultinodeSerializer61, self) 422 base = super(DeploymentMultinodeSerializer61, self)
439 serialized_node = base.serialize_node(node, role) 423 serialized_node = base.serialize_node(node, role)
440 serialized_node['user_node_name'] = node.name 424 serialized_node['user_node_name'] = node.name
441 serialized_node.update(self.generate_vmware_data(node))
442 425
443 return serialized_node 426 return serialized_node
444 427
@@ -451,8 +434,7 @@ class DeploymentMultinodeSerializer61(DeploymentMultinodeSerializer,
451 return serialized_node 434 return serialized_node
452 435
453 436
454class DeploymentHASerializer61(DeploymentHASerializer, 437class DeploymentHASerializer61(DeploymentHASerializer):
455 VmwareDeploymentSerializerMixin):
456 438
457 nova_network_serializer = \ 439 nova_network_serializer = \
458 nova_serializers.NovaNetworkDeploymentSerializer61 440 nova_serializers.NovaNetworkDeploymentSerializer61
@@ -463,7 +445,6 @@ class DeploymentHASerializer61(DeploymentHASerializer,
463 base = super(DeploymentHASerializer61, self) 445 base = super(DeploymentHASerializer61, self)
464 serialized_node = base.serialize_node(node, role) 446 serialized_node = base.serialize_node(node, role)
465 serialized_node['user_node_name'] = node.name 447 serialized_node['user_node_name'] = node.name
466 serialized_node.update(self.generate_vmware_data(node))
467 448
468 return serialized_node 449 return serialized_node
469 450
@@ -475,49 +456,6 @@ class DeploymentHASerializer61(DeploymentHASerializer,
475 serialized_node['user_node_name'] = node.name 456 serialized_node['user_node_name'] = node.name
476 return serialized_node 457 return serialized_node
477 458
478 # Alternate VMWare specific values.
479 # FiXME(who): srogov
480 # This a temporary workaround to keep existing functioanality
481 # after fully implementation of the multi HV support and astute part
482 # for multiple images support, it is need to change
483 # dict image_data['test_vm_image'] to list of dicts
484 def generate_test_vm_image_data(self, node):
485 attrs = node.cluster.attributes
486 image_data = super(
487 DeploymentHASerializer61,
488 self).generate_test_vm_image_data(node)
489
490 images_data = {}
491 images_data['test_vm_image'] = []
492 if attrs.get('editable', {}).get('common', {}). \
493 get('use_vcenter', {}).get('value') is True:
494 image_vmdk_data = deepcopy(image_data['test_vm_image'])
495 img_path = image_vmdk_data['img_path']. \
496 replace('x86_64-disk.img', 'i386-disk.vmdk')
497 image_vmdk_data.update({
498 'img_name': 'TestVM-VMDK',
499 'disk_format': 'vmdk',
500 'img_path': img_path,
501 })
502 properties_data = {
503 'vmware_disktype': 'sparse',
504 'vmware_adaptertype': 'lsiLogic',
505 'hypervisor_type': 'vmware'
506 }
507 glance_properties = self.generate_properties_arguments(
508 properties_data)
509
510 # NOTE(aschultz): properties was added as part of N and should be
511 # used infavor of glance_properties
512 image_vmdk_data['glance_properties'] = glance_properties
513 image_vmdk_data['properties'] = properties_data
514 images_data['test_vm_image'].append(image_vmdk_data)
515 images_data['test_vm_image'].append(image_data['test_vm_image'])
516 else:
517 images_data = image_data
518
519 return images_data
520
521 459
522class DeploymentHASerializer70(DeploymentHASerializer61): 460class DeploymentHASerializer70(DeploymentHASerializer61):
523 # nova_network_serializer is just for compatibility with current BVTs 461 # nova_network_serializer is just for compatibility with current BVTs
diff --git a/nailgun/nailgun/plugins/adapters.py b/nailgun/nailgun/plugins/adapters.py
index b236944..107c518 100644
--- a/nailgun/nailgun/plugins/adapters.py
+++ b/nailgun/nailgun/plugins/adapters.py
@@ -436,8 +436,6 @@ class PluginAdapterV5(PluginAdapterV4):
436 436
437 "components": "components_metadata", 437 "components": "components_metadata",
438 438
439 "vmware_attributes": "vmware_attributes_metadata",
440
441 "os": "operating_system" 439 "os": "operating_system"
442 } 440 }
443 441
diff --git a/nailgun/nailgun/statistics/fuel_statistics/installation_info.py b/nailgun/nailgun/statistics/fuel_statistics/installation_info.py
index 11ab354..482d8c5 100644
--- a/nailgun/nailgun/statistics/fuel_statistics/installation_info.py
+++ b/nailgun/nailgun/statistics/fuel_statistics/installation_info.py
@@ -105,8 +105,6 @@ class InstallationInfo(object):
105 'volumes_ceph', None), 105 'volumes_ceph', None),
106 WhiteListRule(('storage', 'images_ceph', 'value'), 106 WhiteListRule(('storage', 'images_ceph', 'value'),
107 'images_ceph', None), 107 'images_ceph', None),
108 WhiteListRule(('storage', 'images_vcenter', 'value'),
109 'images_vcenter', None),
110 WhiteListRule(('storage', 'ephemeral_ceph', 'value'), 108 WhiteListRule(('storage', 'ephemeral_ceph', 'value'),
111 'ephemeral_ceph', None), 109 'ephemeral_ceph', None),
112 WhiteListRule(('storage', 'objects_ceph', 'value'), 110 WhiteListRule(('storage', 'objects_ceph', 'value'),
@@ -168,17 +166,6 @@ class InstallationInfo(object):
168 'brute_force_protection', bool), 166 'brute_force_protection', bool),
169 ) 167 )
170 168
171 vmware_attributes_white_list = (
172 # ((path, to, property), 'map_to_name', transform_function)
173 WhiteListRule(('value', 'availability_zones', 'cinder', 'enable'),
174 'vmware_az_cinder_enable', None),
175 # We add 'vsphere_cluster' into path for enter into nested list.
176 # Private value of 'vsphere_cluster' is not collected, we only
177 # computes length of the nested list
178 WhiteListRule(('value', 'availability_zones', 'nova_computes',
179 'vsphere_cluster'), 'vmware_az_nova_computes_num', len),
180 )
181
182 plugin_info_white_list = ( 169 plugin_info_white_list = (
183 # ((path, to, property), 'map_to_name', transform_function) 170 # ((path, to, property), 'map_to_name', transform_function)
184 WhiteListRule(('id',), 'id', None), 171 WhiteListRule(('id',), 'id', None),
@@ -278,9 +265,6 @@ class InstallationInfo(object):
278 release = cluster.release 265 release = cluster.release
279 nodes_num = NodeCollection.filter_by( 266 nodes_num = NodeCollection.filter_by(
280 None, cluster_id=cluster.id).count() 267 None, cluster_id=cluster.id).count()
281 vmware_attributes_editable = None
282 if cluster.vmware_attributes:
283 vmware_attributes_editable = cluster.vmware_attributes.editable
284 cluster_info = { 268 cluster_info = {
285 'id': cluster.id, 269 'id': cluster.id,
286 'nodes_num': nodes_num, 270 'nodes_num': nodes_num,
@@ -298,10 +282,6 @@ class InstallationInfo(object):
298 Cluster.get_editable_attributes(cluster), 282 Cluster.get_editable_attributes(cluster),
299 self.attributes_white_list 283 self.attributes_white_list
300 ), 284 ),
301 'vmware_attributes': self.get_attributes(
302 vmware_attributes_editable,
303 self.vmware_attributes_white_list
304 ),
305 'plugin_links': self.get_plugin_links( 285 'plugin_links': self.get_plugin_links(
306 cluster.plugin_links), 286 cluster.plugin_links),
307 'net_provider': cluster.net_provider, 287 'net_provider': cluster.net_provider,
diff --git a/nailgun/nailgun/task/task.py b/nailgun/nailgun/task/task.py
index fec16a4..031792b 100644
--- a/nailgun/nailgun/task/task.py
+++ b/nailgun/nailgun/task/task.py
@@ -57,7 +57,6 @@ from nailgun.task.helpers import TaskHelper
57from nailgun.task.legacy_tasks_adapter import adapt_legacy_tasks 57from nailgun.task.legacy_tasks_adapter import adapt_legacy_tasks
58from nailgun.utils import logs as logs_utils 58from nailgun.utils import logs as logs_utils
59from nailgun.utils.resolvers import TagResolver 59from nailgun.utils.resolvers import TagResolver
60from nailgun.utils.restrictions import VmwareAttributesRestriction
61 60
62 61
63def make_astute_message(task, method, respond_to, args): 62def make_astute_message(task, method, respond_to, args):
@@ -1521,7 +1520,6 @@ class CheckBeforeDeploymentTask(object):
1521 cls._check_nodes_roles(task) 1520 cls._check_nodes_roles(task)
1522 cls._check_ceph(task) 1521 cls._check_ceph(task)
1523 cls._check_public_network(task) 1522 cls._check_public_network(task)
1524 cls._check_vmware_consistency(task)
1525 cls._validate_network_template(task) 1523 cls._validate_network_template(task)
1526 1524
1527 # TODO(asvechnikov): Make an appropriate versioning of tasks 1525 # TODO(asvechnikov): Make an appropriate versioning of tasks
@@ -1661,101 +1659,6 @@ class CheckBeforeDeploymentTask(object):
1661 raise errors.MongoNodesCheckError 1659 raise errors.MongoNodesCheckError
1662 1660
1663 @classmethod 1661 @classmethod
1664 def _check_vmware_consistency(cls, task):
1665 """Checks vmware attributes consistency and proper values."""
1666 attributes = objects.Cluster.get_editable_attributes(task.cluster)
1667 vmware_attributes = task.cluster.vmware_attributes
1668 # Old(< 6.1) clusters haven't vmware support
1669 if vmware_attributes:
1670 cinder_nodes = [node for node in task.cluster.nodes if
1671 'cinder' in node.all_roles]
1672
1673 if not cinder_nodes:
1674 logger.info('There is no any node with "cinder" role provided')
1675
1676 compute_vmware_nodes = [node for node in task.cluster.nodes if
1677 'compute-vmware' in node.all_roles]
1678 if compute_vmware_nodes:
1679 cls._check_vmware_nova_computes(compute_vmware_nodes,
1680 vmware_attributes)
1681
1682 models = {
1683 'settings': attributes,
1684 'default': vmware_attributes.editable,
1685 'cluster': task.cluster,
1686 'current_vcenter': vmware_attributes.editable['value'].get(
1687 'availability_zones')[0],
1688 'glance': vmware_attributes.editable['value'].get('glance'),
1689 'version': settings.VERSION,
1690 'networking_parameters': task.cluster.network_config
1691 }
1692
1693 errors_msg = VmwareAttributesRestriction.check_data(
1694 models=models,
1695 metadata=vmware_attributes.editable['metadata'],
1696 data=vmware_attributes.editable['value'])
1697
1698 if errors_msg:
1699 raise errors.CheckBeforeDeploymentError('\n'.join(errors_msg))
1700
1701 @classmethod
1702 def _check_vmware_nova_computes(cls, compute_vmware_nodes, attributes):
1703 """Check that nova computes settings is correct for cluster nodes
1704
1705 :param compute_vmware_nodes: all node with role compute-vmware that
1706 belongs to cluster
1707 :type compute_vmware_nodes: list of nailgun.db.sqlalchemy.models.Node
1708 instances
1709 :param attributes: cluster vmware_attributes
1710 :type attributes: nailgun.db.sqlalchemy.models.VmwareAttributes
1711 :raises: errors.CheckBeforeDeploymentError
1712 """
1713 compute_nodes_targets = \
1714 objects.VmwareAttributes.get_nova_computes_target_nodes(attributes)
1715 compute_nodes_hostnames = set([t['id'] for t in compute_nodes_targets])
1716
1717 errors_msg = []
1718 cluster_nodes_hostname = set()
1719 not_deleted_nodes_from_computes = set()
1720 not_assigned_nodes_to_computes = set()
1721 for node in compute_vmware_nodes:
1722 node_hostname = node.hostname
1723 if node.pending_deletion:
1724 if node_hostname in compute_nodes_hostnames:
1725 not_deleted_nodes_from_computes.add(node.name)
1726 elif node_hostname not in compute_nodes_hostnames:
1727 not_assigned_nodes_to_computes.add(node.name)
1728
1729 cluster_nodes_hostname.add(node_hostname)
1730
1731 if not_assigned_nodes_to_computes:
1732 errors_msg.append(
1733 "The following compute-vmware nodes are not assigned to "
1734 "any vCenter cluster: {0}".format(
1735 ', '.join(sorted(not_assigned_nodes_to_computes))
1736 )
1737 )
1738 if not_deleted_nodes_from_computes:
1739 errors_msg.append(
1740 "The following nodes are prepared for deletion and "
1741 "couldn't be assigned to any vCenter cluster: {0}".format(
1742 ', '.join(sorted(not_deleted_nodes_from_computes))
1743 ),
1744 )
1745
1746 alien_nodes_names = [t['label'] for t in compute_nodes_targets if
1747 t['id'] not in cluster_nodes_hostname]
1748 if alien_nodes_names:
1749 errors_msg.append(
1750 "The following nodes don't belong to compute-vmware nodes of "
1751 "environment and couldn't be assigned to any vSphere cluster: "
1752 "{0}".format(', '.join(sorted(alien_nodes_names)))
1753 )
1754
1755 if errors_msg:
1756 raise errors.CheckBeforeDeploymentError('\n'.join(errors_msg))
1757
1758 @classmethod
1759 def _validate_network_template(cls, task): 1662 def _validate_network_template(cls, task):
1760 cluster = task.cluster 1663 cluster = task.cluster
1761 1664
diff --git a/nailgun/nailgun/test/base.py b/nailgun/nailgun/test/base.py
index 68ed6f1..65dc76a 100644
--- a/nailgun/nailgun/test/base.py
+++ b/nailgun/nailgun/test/base.py
@@ -331,7 +331,6 @@ class EnvironmentManager(object):
331 'name': 'cluster-api-' + str(randint(0, 1000000)), 331 'name': 'cluster-api-' + str(randint(0, 1000000)),
332 } 332 }
333 editable_attributes = kwargs.pop('editable_attributes', None) 333 editable_attributes = kwargs.pop('editable_attributes', None)
334 vmware_attributes = kwargs.pop('vmware_attributes', None)
335 334
336 if kwargs: 335 if kwargs:
337 cluster_data.update(kwargs) 336 cluster_data.update(kwargs)
@@ -364,8 +363,7 @@ class EnvironmentManager(object):
364 if editable_attributes: 363 if editable_attributes:
365 Cluster.patch_attributes(cluster_db, 364 Cluster.patch_attributes(cluster_db,
366 {'editable': editable_attributes}) 365 {'editable': editable_attributes})
367 if vmware_attributes: 366
368 Cluster.update_vmware_attributes(cluster_db, vmware_attributes)
369 return cluster_db 367 return cluster_db
370 368
371 def create_node( 369 def create_node(
@@ -1074,10 +1072,6 @@ class EnvironmentManager(object):
1074 default_components[0].update(kwargs) 1072 default_components[0].update(kwargs)
1075 return default_components 1073 return default_components
1076 1074
1077 def get_default_vmware_attributes_metadata(self):
1078 return self.read_fixtures(
1079 ['openstack'])[0]['fields']['vmware_attributes_metadata']
1080
1081 def upload_fixtures(self, fxtr_names): 1075 def upload_fixtures(self, fxtr_names):
1082 for fxtr_path in self.fxtr_paths_by_names(fxtr_names): 1076 for fxtr_path in self.fxtr_paths_by_names(fxtr_names):
1083 with open(fxtr_path, "r") as fxtr_file: 1077 with open(fxtr_path, "r") as fxtr_file:
diff --git a/nailgun/nailgun/test/integration/test_attributes.py b/nailgun/nailgun/test/integration/test_attributes.py
index 03cfad1..f999ce7 100644
--- a/nailgun/nailgun/test/integration/test_attributes.py
+++ b/nailgun/nailgun/test/integration/test_attributes.py
@@ -14,7 +14,6 @@
14# License for the specific language governing permissions and limitations 14# License for the specific language governing permissions and limitations
15# under the License. 15# under the License.
16 16
17from mock import patch
18from oslo_serialization import jsonutils 17from oslo_serialization import jsonutils
19import six 18import six
20 19
@@ -604,231 +603,6 @@ class TestAlwaysEditable(BaseIntegrationTest):
604 }]) 603 }])
605 604
606 605
607class TestVmwareAttributes(BaseIntegrationTest):
608
609 def setUp(self):
610 super(TestVmwareAttributes, self).setUp()
611 self.cluster = self.env.create_cluster(api=True)
612
613 def test_vmware_attributes_creation(self):
614 self._set_use_vcenter(self.cluster)
615
616 resp = self.app.get(
617 reverse(
618 'VmwareAttributesHandler',
619 kwargs={'cluster_id': self.cluster['id']}),
620 headers=self.default_headers
621 )
622 release = objects.Release.get_by_uid(self.cluster['release_id'])
623 self.assertEqual(200, resp.status_code)
624
625 attrs = objects.Cluster.get_vmware_attributes(self.cluster)
626 # TODO(apopovych): use dictdiffer 0.3.0 to compare atttributes
627 # one-by-one
628 self.assertEqual(
629 release.vmware_attributes_metadata['editable'],
630 attrs.editable
631 )
632
633 def test_vmware_attributes_update(self):
634 self._set_use_vcenter(self.cluster)
635
636 resp = self.app.put(
637 reverse(
638 'VmwareAttributesHandler',
639 kwargs={'cluster_id': self.cluster['id']}),
640 params=jsonutils.dumps({
641 "editable": {
642 "value": {"foo": "bar"}
643 }
644 }),
645 headers=self.default_headers
646 )
647 self.assertEqual(200, resp.status_code)
648
649 attrs = objects.Cluster.get_vmware_attributes(self.cluster)
650 self.assertEqual('bar', attrs.editable.get('value', {}).get('foo'))
651 attrs.editable.get('value', {}).pop('foo')
652 self.assertEqual(attrs.editable.get('value'), {})
653
654 def test_vmware_attributes_update_with_invalid_json_format(self):
655 self._set_use_vcenter(self.cluster)
656
657 resp = self.app.put(
658 reverse(
659 'VmwareAttributesHandler',
660 kwargs={'cluster_id': self.cluster['id']}),
661 params=jsonutils.dumps({
662 "value": {"foo": "bar"}
663 }),
664 headers=self.default_headers,
665 expect_errors=True
666 )
667
668 self.assertEqual(400, resp.status_code)
669 self.assertEqual(
670 "'editable' is a required property", resp.json_body["message"])
671
672 self._set_use_vcenter(self.cluster)
673
674 resp = self.app.put(
675 reverse(
676 'VmwareAttributesHandler',
677 kwargs={'cluster_id': self.cluster['id']}),
678 params=jsonutils.dumps({
679 "editable": {
680 "metadata": {},
681 "value": {"foo": "bar"}
682 }
683 }),
684 headers=self.default_headers,
685 expect_errors=True
686 )
687
688 self.assertEqual(400, resp.status_code)
689 self.assertEqual(
690 "Metadata shouldn't change", resp.json_body["message"])
691
692 def test_404_if_no_attributes(self):
693 cluster = self.env.create_cluster(api=False)
694 self._set_use_vcenter(cluster)
695
696 self.db.delete(cluster.vmware_attributes)
697 self.db.commit()
698 resp = self.app.put(
699 reverse(
700 'VmwareAttributesHandler',
701 kwargs={'cluster_id': cluster.id}),
702 params=jsonutils.dumps({
703 "editable": {
704 "value": {"foo": "bar"}
705 }
706 }),
707 headers=self.default_headers,
708 expect_errors=True
709 )
710 self.assertEqual(404, resp.status_code)
711
712 def test_not_acceptable_if_cluster_has_not_support_vmware(self):
713 resp = self.app.get(
714 reverse(
715 'VmwareAttributesHandler',
716 kwargs={'cluster_id': self.cluster['id']}),
717 headers=self.default_headers,
718 expect_errors=True
719 )
720 self.assertEqual(400, resp.status_code)
721 self.assertEqual(
722 "Cluster doesn't support vmware configuration",
723 resp.json_body["message"]
724 )
725
726 resp = self.app.put(
727 reverse(
728 'VmwareAttributesHandler',
729 kwargs={'cluster_id': self.cluster['id']}),
730 params=jsonutils.dumps({
731 "editable": {
732 "value": {"foo": "bar"}
733 }
734 }),
735 headers=self.default_headers,
736 expect_errors=True
737 )
738 self.assertEqual(400, resp.status_code)
739 self.assertEqual(
740 "Cluster doesn't support vmware configuration",
741 resp.json_body["message"]
742 )
743
744 @patch('nailgun.db.sqlalchemy.models.Cluster.is_locked', return_value=True)
745 def test_vmware_attributes_update_for_locked_cluster_403(self, locked):
746 self._set_use_vcenter(self.cluster)
747 resp = self.app.put(
748 reverse(
749 'VmwareAttributesHandler',
750 kwargs={'cluster_id': self.cluster.id}),
751 params=jsonutils.dumps({
752 "editable": {
753 "value": {"foo": "bar"}
754 }
755 }),
756 headers=self.default_headers,
757 expect_errors=True
758 )
759 self.assertEqual(403, resp.status_code)
760 self.assertEqual("Environment attributes can't be changed after or "
761 "during deployment.", resp.json_body["message"])
762
763 @patch('objects.Cluster.has_compute_vmware_changes', return_value=True)
764 @patch('nailgun.db.sqlalchemy.models.Cluster.is_locked', return_value=True)
765 def test_vmware_attributes_update_for_locked_cluster_200(
766 self, is_locked_mock, has_compute_mock):
767 self._set_use_vcenter(self.cluster)
768 params = {
769 "editable": {
770 "value": {"foo": "bar"}
771 }}
772 with patch('nailgun.api.v1.handlers.cluster.VmwareAttributesHandler.'
773 'checked_data', return_value=params):
774 resp = self.app.put(
775 reverse(
776 'VmwareAttributesHandler',
777 kwargs={'cluster_id': self.cluster.id}),
778 params=jsonutils.dumps(params),
779 headers=self.default_headers
780 )
781 self.assertEqual(200, resp.status_code)
782 attrs = objects.Cluster.get_vmware_attributes(self.cluster)
783 self.assertEqual('bar', attrs.editable.get('value', {}).get('foo'))
784 attrs.editable.get('value', {}).pop('foo')
785 self.assertEqual(attrs.editable.get('value'), {})
786
787 def _set_use_vcenter(self, cluster):
788 cluster_attrs = objects.Cluster.get_editable_attributes(cluster)
789 cluster_attrs['common']['use_vcenter']['value'] = True
790 objects.Cluster.update_attributes(
791 cluster, {'editable': cluster_attrs})
792
793
794class TestVmwareAttributesDefaults(BaseIntegrationTest):
795
796 def test_get_default_vmware_attributes(self):
797 cluster = self.env.create_cluster(api=True)
798 cluster_attrs = objects.Cluster.get_editable_attributes(cluster)
799 cluster_attrs['common']['use_vcenter']['value'] = True
800 objects.Cluster.update_attributes(
801 cluster, {'editable': cluster_attrs})
802 resp = self.app.get(
803 reverse(
804 'VmwareAttributesDefaultsHandler',
805 kwargs={'cluster_id': cluster['id']}),
806 headers=self.default_headers
807 )
808 release = objects.Release.get_by_uid(cluster['release_id'])
809
810 self.assertEqual(200, resp.status_code)
811 self.assertEqual(
812 release.vmware_attributes_metadata,
813 jsonutils.loads(resp.testbody)
814 )
815
816 def test_not_acceptable_if_cluster_has_not_support_vmware(self):
817 cluster = self.env.create_cluster(api=True)
818 resp = self.app.get(
819 reverse(
820 'VmwareAttributesDefaultsHandler',
821 kwargs={'cluster_id': cluster['id']}),
822 headers=self.default_headers,
823 expect_errors=True
824 )
825 self.assertEqual(400, resp.status_code)
826 self.assertEqual(
827 "Cluster doesn't support vmware configuration",
828 resp.json_body["message"]
829 )
830
831
832class TestAttributesWithPlugins(BaseIntegrationTest): 606class TestAttributesWithPlugins(BaseIntegrationTest):
833 607
834 def setUp(self): 608 def setUp(self):
diff --git a/nailgun/nailgun/test/integration/test_changes_model.py b/nailgun/nailgun/test/integration/test_changes_model.py
index c8e9cfa..e7cb7e4 100644
--- a/nailgun/nailgun/test/integration/test_changes_model.py
+++ b/nailgun/nailgun/test/integration/test_changes_model.py
@@ -38,12 +38,8 @@ class TestClusterChanges(BaseIntegrationTest):
38 name="networks" 38 name="networks"
39 ).all() 39 ).all()
40 self.assertEqual(len(networks_changes), 1) 40 self.assertEqual(len(networks_changes), 1)
41 vmware_changes = self.db.query(ClusterChanges).filter_by(
42 name="vmware_attributes"
43 ).all()
44 self.assertEqual(len(vmware_changes), 1)
45 all_changes = self.db.query(ClusterChanges).all() 41 all_changes = self.db.query(ClusterChanges).all()
46 self.assertEqual(len(all_changes), 3) 42 self.assertEqual(len(all_changes), 2)
47 43
48 def test_node_volumes_modification_adds_pending_changes(self): 44 def test_node_volumes_modification_adds_pending_changes(self):
49 cluster = self.env.create_cluster(api=True) 45 cluster = self.env.create_cluster(api=True)
@@ -162,16 +158,12 @@ class TestClusterChanges(BaseIntegrationTest):
162 name="networks" 158 name="networks"
163 ).all() 159 ).all()
164 self.assertEqual(len(networks_changes), 1) 160 self.assertEqual(len(networks_changes), 1)
165 vmware_changes = self.db.query(ClusterChanges).filter_by(
166 name="vmware_attributes"
167 ).all()
168 self.assertEqual(len(vmware_changes), 1)
169 disks_changes = self.db.query(ClusterChanges).filter_by( 161 disks_changes = self.db.query(ClusterChanges).filter_by(
170 name="disks" 162 name="disks"
171 ).all() 163 ).all()
172 self.assertEqual(len(disks_changes), 1) 164 self.assertEqual(len(disks_changes), 1)
173 all_changes = self.db.query(ClusterChanges).all() 165 all_changes = self.db.query(ClusterChanges).all()
174 self.assertEqual(len(all_changes), 5) 166 self.assertEqual(len(all_changes), 4)
175 167
176 @mock_rpc() 168 @mock_rpc()
177 def test_role_unassignment_drops_changes(self): 169 def test_role_unassignment_drops_changes(self):
diff --git a/nailgun/nailgun/test/integration/test_cluster_collection_handlers.py b/nailgun/nailgun/test/integration/test_cluster_collection_handlers.py
index 5ca9e5f..9b884a4 100644
--- a/nailgun/nailgun/test/integration/test_cluster_collection_handlers.py
+++ b/nailgun/nailgun/test/integration/test_cluster_collection_handlers.py
@@ -149,7 +149,6 @@ class TestHandlers(BaseIntegrationTest):
149 } 149 }
150 } 150 }
151 } 151 }
152 release.vmware_attributes_metadata = {}
153 self.db.add(release) 152 self.db.add(release)
154 self.db.commit() 153 self.db.commit()
155 resp = self.app.post( 154 resp = self.app.post(
diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py
index ca90e6f..6f7dac4 100644
--- a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py
+++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py
@@ -2433,138 +2433,6 @@ class BaseDeploymentSerializer(BaseSerializerTest):
2433 self.env.nodes[0], 'role')['user_node_name'], 2433 self.env.nodes[0], 'role')['user_node_name'],
2434 self.node_name) 2434 self.node_name)
2435 2435
2436 def check_generate_test_vm_image_data(self):
2437 img_name = 'TestVM-VMDK'
2438 disk_format = 'vmdk'
2439 img_path = '/opt/vm/cirros-i386-disk.vmdk'
2440 properties_data = {
2441 'vmware_disktype': 'sparse',
2442 'vmware_adaptertype': 'lsiLogic',
2443 'hypervisor_type': 'vmware'
2444 }
2445 glance_properties = []
2446 for k, v in six.iteritems(properties_data):
2447 glance_properties.append('--property {k}={v}'.format(k=k, v=v))
2448
2449 self.assertEqual(
2450 len(self.serializer.generate_test_vm_image_data(
2451 self.env.nodes[0])['test_vm_image']), 2)
2452
2453 self.assertEqual(
2454 self.serializer.generate_test_vm_image_data(
2455 self.env.nodes[0])['test_vm_image'][0]['img_name'],
2456 img_name)
2457
2458 self.assertEqual(
2459 self.serializer.generate_test_vm_image_data(
2460 self.env.nodes[0])['test_vm_image'][0]['disk_format'],
2461 disk_format)
2462
2463 self.assertEqual(
2464 self.serializer.generate_test_vm_image_data(
2465 self.env.nodes[0])['test_vm_image'][0]['img_path'],
2466 img_path)
2467
2468 self.assertEqual(
2469 self.serializer.generate_test_vm_image_data(
2470 self.env.nodes[0])['test_vm_image'][0]['glance_properties'],
2471 ' '.join(glance_properties))
2472
2473 self.assertEqual(
2474 self.serializer.generate_test_vm_image_data(
2475 self.env.nodes[0])['test_vm_image'][0]['properties'],
2476 properties_data)
2477
2478 def check_generate_vmware_attributes_data(self):
2479 cluster_db = self.db.query(Cluster).get(self.cluster['id'])
2480 cluster_attrs = objects.Cluster.get_editable_attributes(cluster_db)
2481 cluster_attrs.get('common', {}).setdefault('use_vcenter', {})
2482 cluster_attrs['common']['use_vcenter']['value'] = True
2483
2484 objects.Cluster.update_attributes(
2485 cluster_db, {'editable': cluster_attrs})
2486 setattr(
2487 cluster_db.vmware_attributes,
2488 'editable',
2489 self.vm_data[0]['editable'])
2490 self.db.flush()
2491
2492 result = self.serializer.serialize_node(
2493 self.env.nodes[0], 'controller'
2494 )
2495
2496 self.assertEqual(len(result['vcenter']['computes']), 4)
2497
2498 self.assertIn(
2499 result['vcenter']['computes'][0]['service_name'],
2500 ['Compute 1', 'Compute 3'])
2501
2502 self.assertIn(
2503 result['vcenter']['computes'][1]['service_name'],
2504 ['Compute 1', 'Compute 3'])
2505
2506 # check compute parameters
2507 self.assertEqual(
2508 result['vcenter']['computes'][0]['availability_zone_name'],
2509 "Zone 1")
2510 self.assertEqual(
2511 result['vcenter']['computes'][0]['vc_host'],
2512 "1.2.3.4")
2513 self.assertEqual(
2514 result['vcenter']['computes'][0]['vc_user'],
2515 "admin")
2516 self.assertEqual(
2517 result['vcenter']['computes'][0]['vc_password'],
2518 "secret")
2519 self.assertTrue(result['vcenter']['computes'][0]['vc_insecure'])
2520 self.assertEqual(
2521 result['vcenter']['computes'][0]['vc_ca_file'],
2522 "file_blob")
2523 self.assertEqual(
2524 result['vcenter']['computes'][0]['vc_cluster'],
2525 "cluster1")
2526
2527 # Be sure that "$" was converted to "$$"
2528 self.assertEqual(
2529 result['vcenter']['computes'][2]['vc_user'],
2530 "user$$")
2531 self.assertEqual(
2532 result['vcenter']['computes'][2]['vc_password'],
2533 "pass$$word")
2534 self.assertEqual(
2535 result['vcenter']['computes'][2]['datastore_regex'],
2536 "^openstack-[0-9]$$")
2537
2538 self.assertTrue(result['use_vcenter'])
2539 self.assertEqual(result['vcenter']['esxi_vlan_interface'], "eth0")
2540
2541 # check cinder parameters
2542 self.assertEqual(len(result['cinder']['instances']), 2)
2543 self.assertEqual(
2544 result['cinder']['instances'][0]['availability_zone_name'],
2545 "Zone 1")
2546 self.assertEqual(
2547 result['cinder']['instances'][0]['vc_host'],
2548 "1.2.3.4")
2549 self.assertEqual(
2550 result['cinder']['instances'][0]['vc_user'],
2551 "admin")
2552 self.assertEqual(
2553 result['cinder']['instances'][0]['vc_password'],
2554 "secret")
2555 self.assertTrue(result['cinder']['instances'][0]['vc_insecure'])
2556 self.assertEqual(
2557 result['cinder']['instances'][0]['vc_ca_file'],
2558 "file_blob")
2559
2560 self.assertEqual(result['glance']['vc_host'], "1.2.3.4")
2561 self.assertEqual(result['glance']['vc_user'], "admin")
2562 self.assertEqual(result['glance']['vc_password'], "secret")
2563 self.assertEqual(result['glance']['vc_datacenter'], "test_datacenter")
2564 self.assertEqual(result['glance']['vc_datastore'], "test_datastore")
2565 self.assertTrue(result['glance']['vc_insecure'])
2566 self.assertEqual(result['glance']['vc_ca_file'], "file_blob")
2567
2568 def check_no_murano_data(self): 2436 def check_no_murano_data(self):
2569 glance_properties = self.serializer.generate_test_vm_image_data( 2437 glance_properties = self.serializer.generate_test_vm_image_data(
2570 self.env.nodes[0])['test_vm_image']['glance_properties'] 2438 self.env.nodes[0])['test_vm_image']['glance_properties']
@@ -2629,7 +2497,6 @@ class TestDeploymentMultinodeSerializer61(BaseDeploymentSerializer):
2629 self.cluster = self.create_env(consts.CLUSTER_MODES.multinode) 2497 self.cluster = self.create_env(consts.CLUSTER_MODES.multinode)
2630 objects.Cluster.prepare_for_deployment(self.env.clusters[-1]) 2498 objects.Cluster.prepare_for_deployment(self.env.clusters[-1])
2631 self.serializer = DeploymentMultinodeSerializer61(self.cluster) 2499 self.serializer = DeploymentMultinodeSerializer61(self.cluster)
2632 self.vm_data = self.env.read_fixtures(['vmware_attributes'])
2633 2500
2634 def test_serialize_node(self): 2501 def test_serialize_node(self):
2635 self.check_serialize_node() 2502 self.check_serialize_node()
@@ -2637,9 +2504,6 @@ class TestDeploymentMultinodeSerializer61(BaseDeploymentSerializer):
2637 def test_serialize_node_for_node_list(self): 2504 def test_serialize_node_for_node_list(self):
2638 self.check_serialize_node_for_node_list() 2505 self.check_serialize_node_for_node_list()
2639 2506
2640 def test_generate_vmware_attributes_data(self):
2641 self.check_generate_vmware_attributes_data()
2642
2643 def test_glance_properties(self): 2507 def test_glance_properties(self):
2644 self.check_no_murano_data() 2508 self.check_no_murano_data()
2645 2509
@@ -2698,15 +2562,11 @@ class TestDeploymentHASerializer61(BaseDeploymentSerializer):
2698 self.cluster = self.create_env(consts.CLUSTER_MODES.ha_compact) 2562 self.cluster = self.create_env(consts.CLUSTER_MODES.ha_compact)
2699 objects.Cluster.prepare_for_deployment(self.env.clusters[-1]) 2563 objects.Cluster.prepare_for_deployment(self.env.clusters[-1])
2700 self.serializer = DeploymentHASerializer61(self.cluster) 2564 self.serializer = DeploymentHASerializer61(self.cluster)
2701 self.vm_data = self.env.read_fixtures(['vmware_attributes'])
2702 2565
2703 def check_generate_test_vm_image_data(self): 2566 def check_generate_test_vm_image_data(self):
2704 kvm_img_name = 'TestVM' 2567 kvm_img_name = 'TestVM'
2705 kvm_img_disk_format = 'qcow2' 2568 kvm_img_disk_format = 'qcow2'
2706 kvm_img_path = '/opt/vm/cirros-x86_64-disk.img' 2569 kvm_img_path = '/opt/vm/cirros-x86_64-disk.img'
2707 vmdk_img_name = 'TestVM-VMDK'
2708 vmdk_disk_format = 'vmdk'
2709 vmdk_img_path = '/opt/vm/cirros-i386-disk.vmdk'
2710 2570
2711 self.assertEqual( 2571 self.assertEqual(
2712 len(self.serializer.generate_test_vm_image_data( 2572 len(self.serializer.generate_test_vm_image_data(
@@ -2714,21 +2574,6 @@ class TestDeploymentHASerializer61(BaseDeploymentSerializer):
2714 2574
2715 self.assertEqual( 2575 self.assertEqual(
2716 self.serializer.generate_test_vm_image_data( 2576 self.serializer.generate_test_vm_image_data(
2717 self.env.nodes[0])['test_vm_image'][0]['img_name'],
2718 vmdk_img_name)
2719
2720 self.assertEqual(
2721 self.serializer.generate_test_vm_image_data(
2722 self.env.nodes[0])['test_vm_image'][0]['disk_format'],
2723 vmdk_disk_format)
2724
2725 self.assertEqual(
2726 self.serializer.generate_test_vm_image_data(
2727 self.env.nodes[0])['test_vm_image'][0]['img_path'],
2728 vmdk_img_path)
2729
2730 self.assertEqual(
2731 self.serializer.generate_test_vm_image_data(
2732 self.env.nodes[0])['test_vm_image'][1]['img_name'], 2577 self.env.nodes[0])['test_vm_image'][1]['img_name'],
2733 kvm_img_name) 2578 kvm_img_name)
2734 2579
@@ -2748,19 +2593,6 @@ class TestDeploymentHASerializer61(BaseDeploymentSerializer):
2748 def test_serialize_node_for_node_list(self): 2593 def test_serialize_node_for_node_list(self):
2749 self.check_serialize_node_for_node_list() 2594 self.check_serialize_node_for_node_list()
2750 2595
2751 def test_generate_test_vm_image_data(self):
2752 cluster_db = self.db.query(Cluster).get(self.cluster['id'])
2753 cluster_attrs = objects.Cluster.get_editable_attributes(cluster_db)
2754 cluster_attrs['common'].setdefault('use_vcenter', {})
2755 cluster_attrs['common']['use_vcenter']['value'] = True
2756
2757 objects.Cluster.update_attributes(
2758 cluster_db, {'editable': cluster_attrs})
2759 self.check_generate_test_vm_image_data()
2760
2761 def test_generate_vmware_attributes_data(self):
2762 self.check_generate_vmware_attributes_data()
2763
2764 def test_glance_properties(self): 2596 def test_glance_properties(self):
2765 self.check_no_murano_data() 2597 self.check_no_murano_data()
2766 2598
diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py
index e8fb61c..05e1ce2 100644
--- a/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py
+++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py
@@ -266,7 +266,6 @@ class BaseTestDeploymentAttributesSerialization70(BaseDeploymentSerializer,
266 self.cluster_db, self.cluster_db.nodes) 266 self.cluster_db, self.cluster_db.nodes)
267 self.serialized_for_astute = deployment_info_to_legacy( 267 self.serialized_for_astute = deployment_info_to_legacy(
268 self.serialized_for_astute) 268 self.serialized_for_astute)
269 self.vm_data = self.env.read_fixtures(['vmware_attributes'])
270 269
271 def create_env(self, mode): 270 def create_env(self, mode):
272 release = self.patch_net_roles_for_release() 271 release = self.patch_net_roles_for_release()
@@ -507,20 +506,6 @@ class TestDeploymentAttributesSerialization70(
507 self.assertEqual(v['network_roles'], dict(network_roles)) 506 self.assertEqual(v['network_roles'], dict(network_roles))
508 self.check_vips_serialized(node_data) 507 self.check_vips_serialized(node_data)
509 508
510 def test_generate_vmware_attributes_data(self):
511 self.check_generate_vmware_attributes_data()
512
513 result = self.serializer.serialize_node(
514 self.env.nodes[0], 'compute-vmware'
515 )
516
517 self.assertEqual(
518 result['vcenter']['computes'][0]['target_node'],
519 "test_target_node")
520 self.assertEqual(
521 result['vcenter']['computes'][2]['target_node'],
522 "controllers")
523
524 509
525class TestDeploymentAttributesSerializationSegmentationGre70( 510class TestDeploymentAttributesSerializationSegmentationGre70(
526 TestDeploymentAttributesSerialization70 511 TestDeploymentAttributesSerialization70
@@ -670,20 +655,6 @@ class TestDeploymentSerializationForNovaNetwork70(
670 ) 655 )
671 self.check_vips_serialized(node_data) 656 self.check_vips_serialized(node_data)
672 657
673 def test_generate_vmware_attributes_data(self):
674 self.check_generate_vmware_attributes_data()
675
676 result = self.serializer.serialize_node(
677 self.env.nodes[0], 'compute-vmware'
678 )
679
680 self.assertEqual(
681 result['vcenter']['computes'][0]['target_node'],
682 "test_target_node")
683 self.assertEqual(
684 result['vcenter']['computes'][2]['target_node'],
685 "controllers")
686
687 658
688class TestPluginDeploymentTasksInjection70(base.BaseIntegrationTest): 659class TestPluginDeploymentTasksInjection70(base.BaseIntegrationTest):
689 env_version = '2015.1.0-7.0' 660 env_version = '2015.1.0-7.0'
diff --git a/nailgun/nailgun/test/unit/fuel_statistics_tests/test_installation_info.py b/nailgun/nailgun/test/unit/fuel_statistics_tests/test_installation_info.py
index 8a09087..7ff67df 100644
--- a/nailgun/nailgun/test/unit/fuel_statistics_tests/test_installation_info.py
+++ b/nailgun/nailgun/test/unit/fuel_statistics_tests/test_installation_info.py
@@ -22,7 +22,6 @@ from nailgun import consts
22from nailgun.db.sqlalchemy import models 22from nailgun.db.sqlalchemy import models
23from nailgun.objects import Cluster 23from nailgun.objects import Cluster
24from nailgun.objects import ReleaseCollection 24from nailgun.objects import ReleaseCollection
25from nailgun.objects import VmwareAttributes
26from nailgun.settings import settings 25from nailgun.settings import settings
27from nailgun.statistics.fuel_statistics.installation_info \ 26from nailgun.statistics.fuel_statistics.installation_info \
28 import InstallationInfo 27 import InstallationInfo
@@ -128,29 +127,6 @@ class TestInstallationInfo(BaseTestCase):
128 result = info.get_attributes(attrs, info.attributes_white_list) 127 result = info.get_attributes(attrs, info.attributes_white_list)
129 self.assertDictEqual({}, result) 128 self.assertDictEqual({}, result)
130 129
131 def test_clusters_info_no_vmware_attributes_exception(self):
132 self.env.upload_fixtures(['openstack'])
133 info = InstallationInfo()
134 release = ReleaseCollection.filter_by(
135 None, operating_system=consts.RELEASE_OS.ubuntu)
136 nodes_params = [
137 {'roles': ['compute']},
138 {'roles': ['compute']},
139 {'roles': ['controller']}
140 ]
141 cluster = self.env.create(
142 cluster_kwargs={
143 'release_id': release[0].id,
144 'mode': consts.CLUSTER_MODES.ha_compact,
145 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron},
146 nodes_kwargs=nodes_params
147 )
148 self.env.create_node(
149 {'status': consts.NODE_STATUSES.discover})
150 VmwareAttributes.delete(cluster.vmware_attributes)
151 self.env.db.flush()
152 self.assertNotRaises(AttributeError, info.get_clusters_info)
153
154 def test_clusters_info(self): 130 def test_clusters_info(self):
155 self.env.upload_fixtures(['openstack']) 131 self.env.upload_fixtures(['openstack'])
156 info = InstallationInfo() 132 info = InstallationInfo()
@@ -433,7 +409,6 @@ class TestInstallationInfo(BaseTestCase):
433 ('syslog', 'syslog_server'), ('workloads_collector', 'password'), 409 ('syslog', 'syslog_server'), ('workloads_collector', 'password'),
434 ('workloads_collector', 'tenant'), 410 ('workloads_collector', 'tenant'),
435 ('workloads_collector', 'user'), 411 ('workloads_collector', 'user'),
436 ('common', 'use_vcenter'), # removed attribute
437 ('murano_settings', 'murano_repo_url'), 412 ('murano_settings', 'murano_repo_url'),
438 ('use_fedora_lt', 'kernel'), 413 ('use_fedora_lt', 'kernel'),
439 ('public_ssl', 'cert_data'), ('public_ssl', 'hostname'), 414 ('public_ssl', 'cert_data'), ('public_ssl', 'hostname'),
@@ -468,25 +443,6 @@ class TestInstallationInfo(BaseTestCase):
468 for path in expected_paths: 443 for path in expected_paths:
469 self.assertIn(path, actual_paths) 444 self.assertIn(path, actual_paths)
470 445
471 def test_all_cluster_vmware_attributes_in_white_list(self):
472 cluster = self.env.create(nodes_kwargs=[{'roles': ['compute']}])
473 self.env.create_node(status=consts.NODE_STATUSES.discover)
474
475 expected_paths = self._find_leafs_paths(
476 cluster.vmware_attributes.editable,
477 leafs_names=('vsphere_cluster', 'enable'))
478
479 # Removing leaf name from expected paths
480 actual_paths = [rule.path[:-1] for rule in
481 InstallationInfo.vmware_attributes_white_list]
482 # If test failed here it means, that you have added cluster vmware
483 # attributes and they are not added into
484 # InstallationInfo.vmware_attributes_white_list
485 # If you don't know what should be added into white list, contact
486 # fuel-stats team please.
487 for path in expected_paths:
488 self.assertIn(path, actual_paths)
489
490 def test_all_plugin_data_collected(self): 446 def test_all_plugin_data_collected(self):
491 cluster = self.env.create_cluster(api=False) 447 cluster = self.env.create_cluster(api=False)
492 self.env.create_plugin(api=False, cluster=cluster) 448 self.env.create_plugin(api=False, cluster=cluster)
@@ -552,7 +508,6 @@ class TestInstallationInfo(BaseTestCase):
552 def test_white_list_unique_names(self): 508 def test_white_list_unique_names(self):
553 white_list_attrs = ( 509 white_list_attrs = (
554 'attributes_white_list', 510 'attributes_white_list',
555 'vmware_attributes_white_list',
556 'plugin_info_white_list', 511 'plugin_info_white_list',
557 'node_info_white_list' 512 'node_info_white_list'
558 ) 513 )
diff --git a/nailgun/nailgun/test/unit/test_deployment_graph_object.py b/nailgun/nailgun/test/unit/test_deployment_graph_object.py
index 4b0f24d..8b4eb0e 100644
--- a/nailgun/nailgun/test/unit/test_deployment_graph_object.py
+++ b/nailgun/nailgun/test/unit/test_deployment_graph_object.py
@@ -55,8 +55,7 @@ JSON_TASKS = [
55 'type': 'puppet', 55 'type': 'puppet',
56 'version': '2.0.0', 56 'version': '2.0.0',
57 'groups': ['primary-controller', 'controller', 'compute', 57 'groups': ['primary-controller', 'controller', 'compute',
58 'compute-vmware', 'cinder', 'cinder-vmware', 58 'cinder', 'primary-mongo', 'mongo', 'ceph-osd', 'virt'],
59 'primary-mongo', 'mongo', 'ceph-osd', 'virt'],
60 'requires': ['firewall'], 59 'requires': ['firewall'],
61 'condition': "(settings:public_ssl.horizon.value == true or settings:" 60 'condition': "(settings:public_ssl.horizon.value == true or settings:"
62 "public_ssl.services.value == true) and settings:" 61 "public_ssl.services.value == true) and settings:"
@@ -124,8 +123,7 @@ EXPECTED_TASKS = [
124 'type': 'puppet', 123 'type': 'puppet',
125 'version': '2.0.0', 124 'version': '2.0.0',
126 'groups': ['primary-controller', 'controller', 'compute', 125 'groups': ['primary-controller', 'controller', 'compute',
127 'compute-vmware', 'cinder', 'cinder-vmware', 126 'cinder', 'primary-mongo', 'mongo', 'ceph-osd', 'virt'],
128 'primary-mongo', 'mongo', 'ceph-osd', 'virt'],
129 'requires': ['firewall'], 127 'requires': ['firewall'],
130 'condition': "(settings:public_ssl.horizon.value == true or " 128 'condition': "(settings:public_ssl.horizon.value == true or "
131 "settings:public_ssl.services.value == true) " 129 "settings:public_ssl.services.value == true) "
diff --git a/nailgun/nailgun/test/unit/test_objects.py b/nailgun/nailgun/test/unit/test_objects.py
index 379edda..d3aad5d 100644
--- a/nailgun/nailgun/test/unit/test_objects.py
+++ b/nailgun/nailgun/test/unit/test_objects.py
@@ -1500,27 +1500,6 @@ class TestClusterObject(BaseTestCase):
1500 'cluster': {u'net_provider': u'test_provider'}} 1500 'cluster': {u'net_provider': u'test_provider'}}
1501 ) 1501 )
1502 1502
1503 def test_cluster_has_compute_vmware_changes(self):
1504 cluster = self.env.create_cluster(api=False)
1505 ready_compute_vmware_node = self.env.create_node(
1506 cluster_id=cluster.id,
1507 roles=['compute-vmware'],
1508 status=consts.NODE_STATUSES.ready
1509 )
1510 self.env.create_node(cluster_id=cluster.id, pending_addition=True,
1511 pending_roles=['controller'])
1512 self.assertFalse(objects.Cluster.has_compute_vmware_changes(cluster))
1513
1514 pending_compute_vmware_node = self.env.create_node(
1515 cluster_id=cluster.id,
1516 pending_roles=["compute-vmware"]
1517 )
1518 self.assertTrue(objects.Cluster.has_compute_vmware_changes(cluster))
1519 objects.Node.delete(pending_compute_vmware_node)
1520 objects.Node.update(
1521 ready_compute_vmware_node, {'pending_deletion': True})
1522 self.assertTrue(objects.Cluster.has_compute_vmware_changes(cluster))
1523
1524 def test_enable_settings_by_components(self): 1503 def test_enable_settings_by_components(self):
1525 components = [{ 1504 components = [{
1526 'name': 'network:neutron:tun', 1505 'name': 'network:neutron:tun',
diff --git a/nailgun/nailgun/test/unit/test_restriction.py b/nailgun/nailgun/test/unit/test_restriction.py
index 9ec9679..ed8544d 100644
--- a/nailgun/nailgun/test/unit/test_restriction.py
+++ b/nailgun/nailgun/test/unit/test_restriction.py
@@ -19,13 +19,11 @@ import yaml
19 19
20from nailgun import errors 20from nailgun import errors
21from nailgun import objects 21from nailgun import objects
22from nailgun.settings import settings
23from nailgun.test import base 22from nailgun.test import base
24from nailgun.utils.restrictions import AttributesRestriction 23from nailgun.utils.restrictions import AttributesRestriction
25from nailgun.utils.restrictions import ComponentsRestrictions 24from nailgun.utils.restrictions import ComponentsRestrictions
26from nailgun.utils.restrictions import LimitsMixin 25from nailgun.utils.restrictions import LimitsMixin
27from nailgun.utils.restrictions import RestrictionBase 26from nailgun.utils.restrictions import RestrictionBase
28from nailgun.utils.restrictions import VmwareAttributesRestriction
29 27
30 28
31DATA = """ 29DATA = """
@@ -336,148 +334,6 @@ class TestAttributesRestriction(base.BaseTestCase):
336 self.assertListEqual(errs, []) 334 self.assertListEqual(errs, [])
337 335
338 336
339class TestVmwareAttributesRestriction(base.BaseTestCase):
340
341 def setUp(self):
342 super(TestVmwareAttributesRestriction, self).setUp()
343 self.cluster = self.env.create(
344 cluster_kwargs={
345 'api': False
346 }
347 )
348 self.vm_data = self.env.read_fixtures(['vmware_attributes'])[0]
349
350 def _get_models(self, attributes, vmware_attributes):
351 return {
352 'settings': attributes,
353 'default': vmware_attributes['editable'],
354 'current_vcenter': vmware_attributes['editable']['value'].get(
355 'availability_zones')[0],
356 'glance': vmware_attributes['editable']['value'].get('glance'),
357 'cluster': self.cluster,
358 'version': settings.VERSION,
359 'networking_parameters': self.cluster.network_config
360 }
361
362 def test_check_data_with_empty_values_without_restrictions(self):
363 attributes = objects.Cluster.get_editable_attributes(self.cluster)
364 attributes['common']['use_vcenter']['value'] = True
365 attributes['storage']['images_vcenter']['value'] = True
366 vmware_attributes = self.vm_data.copy()
367 empty_values = {
368 "availability_zones": [
369 {
370 "az_name": "",
371 "vcenter_host": "",
372 "vcenter_username": "",
373 "vcenter_password": "",
374 "vcenter_security_disabled": "",
375 "vcenter_ca_file": {},
376 "nova_computes": [
377 {
378 "vsphere_cluster": "",
379 "service_name": "",
380 "datastore_regex": ""
381 }
382 ]
383 }
384 ],
385 "network": {
386 "esxi_vlan_interface": ""
387 },
388 "glance": {
389 "vcenter_host": "",
390 "vcenter_username": "",
391 "vcenter_password": "",
392 "datacenter": "",
393 "datastore": "",
394 "vcenter_security_disabled": "",
395 "ca_file": {}
396 }
397 }
398 # Update value with empty value
399 vmware_attributes['editable']['value'] = empty_values
400 models = self._get_models(attributes, vmware_attributes)
401
402 errs = VmwareAttributesRestriction.check_data(
403 models=models,
404 metadata=vmware_attributes['editable']['metadata'],
405 data=vmware_attributes['editable']['value'])
406 self.assertItemsEqual(
407 errs,
408 ['Empty cluster', 'Empty host', 'Empty username',
409 'Empty password', 'Empty datacenter', 'Empty datastore'])
410
411 def test_check_data_with_invalid_values_without_restrictions(self):
412 # Disable restrictions
413 attributes = objects.Cluster.get_editable_attributes(self.cluster)
414 attributes['common']['use_vcenter']['value'] = True
415 attributes['storage']['images_vcenter']['value'] = True
416 # value data taken from fixture one cluster of
417 # nova computes left empty
418 vmware_attributes = self.vm_data.copy()
419 models = self._get_models(attributes, vmware_attributes)
420
421 errs = VmwareAttributesRestriction.check_data(
422 models=models,
423 metadata=vmware_attributes['editable']['metadata'],
424 data=vmware_attributes['editable']['value'])
425 self.assertItemsEqual(errs, ['Empty cluster'])
426
427 def test_check_data_with_invalid_values_and_with_restrictions(self):
428 attributes = objects.Cluster.get_editable_attributes(self.cluster)
429 # fixture have restrictions enabled for glance that's why
430 # only 'Empty cluster' should returned
431 vmware_attributes = self.vm_data.copy()
432 models = self._get_models(attributes, vmware_attributes)
433
434 errs = VmwareAttributesRestriction.check_data(
435 models=models,
436 metadata=vmware_attributes['editable']['metadata'],
437 data=vmware_attributes['editable']['value'])
438 self.assertItemsEqual(errs, ['Empty cluster'])
439
440 def test_check_data_with_valid_values_and_with_restrictions(self):
441 attributes = objects.Cluster.get_editable_attributes(self.cluster)
442 vmware_attributes = self.vm_data.copy()
443 # Set valid data for clusters
444 for i, azone in enumerate(
445 vmware_attributes['editable']['value']['availability_zones']):
446 for j, ncompute in enumerate(azone['nova_computes']):
447 ncompute['vsphere_cluster'] = 'cluster-{0}-{1}'.format(i, j)
448
449 models = self._get_models(attributes, vmware_attributes)
450
451 errs = VmwareAttributesRestriction.check_data(
452 models=models,
453 metadata=vmware_attributes['editable']['metadata'],
454 data=vmware_attributes['editable']['value'])
455 self.assertItemsEqual(errs, [])
456
457 def test_check_data_with_valid_values_and_without_restrictions(self):
458 # Disable restrictions
459 attributes = objects.Cluster.get_editable_attributes(self.cluster)
460 attributes['common']['use_vcenter']['value'] = True
461 attributes['storage']['images_vcenter']['value'] = True
462 vmware_attributes = self.vm_data.copy()
463 # Set valid data for clusters
464 for i, azone in enumerate(
465 vmware_attributes['editable']['value']['availability_zones']):
466 for j, ncompute in enumerate(azone['nova_computes']):
467 ncompute['vsphere_cluster'] = 'cluster-{0}-{1}'.format(i, j)
468 # Set valid data for glance
469 glance = vmware_attributes['editable']['value']['glance']
470 glance['datacenter'] = 'test_datacenter'
471 glance['datastore'] = 'test_datastore'
472 models = self._get_models(attributes, vmware_attributes)
473
474 errs = VmwareAttributesRestriction.check_data(
475 models=models,
476 metadata=vmware_attributes['editable']['metadata'],
477 data=vmware_attributes['editable']['value'])
478 self.assertItemsEqual(errs, [])
479
480
481class TestComponentsRestrictions(base.BaseTestCase): 337class TestComponentsRestrictions(base.BaseTestCase):
482 338
483 def setUp(self): 339 def setUp(self):
diff --git a/nailgun/nailgun/test/unit/test_task.py b/nailgun/nailgun/test/unit/test_task.py
index 1603a3f..7be2e92 100644
--- a/nailgun/nailgun/test/unit/test_task.py
+++ b/nailgun/nailgun/test/unit/test_task.py
@@ -614,96 +614,6 @@ class TestCheckBeforeDeploymentTask(BaseTestCase):
614 task.CheckBeforeDeploymentTask._check_public_network, 614 task.CheckBeforeDeploymentTask._check_public_network,
615 self.task) 615 self.task)
616 616
617 def test_check_missed_nodes_vmware_nova_computes(self):
618 operational_node = self.env.create_node(
619 roles=['compute-vmware'],
620 cluster_id=self.cluster.id,
621 name='node-1'
622 )
623 pending_addition_node = self.env.create_node(
624 roles=['compute-vmware'],
625 cluster_id=self.cluster.id,
626 pending_addition=True,
627 name='node-2'
628 )
629 msg = ("The following compute-vmware nodes are not assigned to "
630 "any vCenter cluster: {0}").format(', '.join(
631 sorted([operational_node.name, pending_addition_node.name])
632 ))
633 with self.assertRaisesRegexp(errors.CheckBeforeDeploymentError, msg):
634 task.CheckBeforeDeploymentTask._check_vmware_consistency(self.task)
635
636 @mock.patch('objects.VmwareAttributes.get_nova_computes_target_nodes')
637 def test_check_not_deleted_nodes_vmware_nova_computes(self, target_nodes):
638 operational_node = self.env.create_node(
639 roles=['compute-vmware'],
640 cluster_id=self.cluster.id,
641 name='node-1'
642 )
643 pending_deletion_node = self.env.create_node(
644 roles=['compute-vmware'],
645 cluster_id=self.cluster.id,
646 pending_deletion=True,
647 name='node-2'
648 )
649 target_nodes.return_value = [{
650 'id': operational_node.hostname,
651 'label': operational_node.name
652 }, {
653 'id': pending_deletion_node.hostname,
654 'label': pending_deletion_node.name
655 }]
656 msg = ("The following nodes are prepared for deletion and couldn't be "
657 "assigned to any vCenter cluster: {0}".format(
658 pending_deletion_node.name))
659 with self.assertRaisesRegexp(errors.CheckBeforeDeploymentError, msg):
660 task.CheckBeforeDeploymentTask._check_vmware_consistency(self.task)
661
662 @mock.patch('objects.VmwareAttributes.get_nova_computes_target_nodes')
663 def test_check_extra_nodes_vmware_nova_computes(self, target_nodes):
664 operational_node = self.env.create_node(
665 roles=['compute-vmware'],
666 cluster_id=self.cluster.id,
667 name='node-1'
668 )
669 non_cluster_node = self.env.create_node(
670 roles=['compute-vmware'],
671 name='node-2'
672 )
673 other_role_node = self.env.create_node(
674 cluster_id=self.cluster.id,
675 name='node-3'
676 )
677 target_nodes.return_value = [{
678 'id': operational_node.hostname,
679 'label': operational_node.name
680 }, {
681 'id': non_cluster_node.hostname,
682 'label': non_cluster_node.name
683 }, {
684 'id': other_role_node.hostname,
685 'label': other_role_node.name
686 }]
687 msg = ("The following nodes don't belong to compute-vmware nodes of "
688 "environment and couldn't be assigned to any vSphere cluster: "
689 "{0}".format(', '.join(
690 sorted([non_cluster_node.name, other_role_node.name]))
691 ))
692 with self.assertRaisesRegexp(errors.CheckBeforeDeploymentError, msg):
693 task.CheckBeforeDeploymentTask._check_vmware_consistency(self.task)
694
695 @mock.patch.object(
696 task, 'fire_callback_on_before_deployment_check')
697 @mock.patch.object(
698 task.CheckBeforeDeploymentTask, '_check_sriov_properties')
699 @mock.patch.object(
700 task.CheckBeforeDeploymentTask, '_check_dpdk_properties')
701 def test_execute_w_old_release(self, dpdk_m, sriov_m, callback_m):
702 task.CheckBeforeDeploymentTask.execute(self.task)
703 callback_m.assert_called_once_with(self.cluster, [])
704 self.assertEqual(0, dpdk_m.call_count)
705 self.assertEqual(0, sriov_m.call_count)
706
707 617
708class TestDeployTask(BaseTestCase): 618class TestDeployTask(BaseTestCase):
709 619
diff --git a/nailgun/nailgun/test/unit/test_vmware_attributes_validator.py b/nailgun/nailgun/test/unit/test_vmware_attributes_validator.py
deleted file mode 100644
index 382a6af..0000000
--- a/nailgun/nailgun/test/unit/test_vmware_attributes_validator.py
+++ /dev/null
@@ -1,443 +0,0 @@
1# -*- coding: utf-8 -*-
2# Copyright 2015 Mirantis, Inc.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from copy import deepcopy
17from mock import patch
18
19from nailgun.api.v1.validators.cluster import VmwareAttributesValidator
20from nailgun import consts
21from nailgun import errors
22from nailgun import objects
23from nailgun.test.base import BaseTestCase
24
25
26class TestAttributesValidator(BaseTestCase):
27 def setUp(self):
28 super(TestAttributesValidator, self).setUp()
29 self.cluster = self.env.create(
30 cluster_kwargs={
31 "api": False,
32 "vmware_attributes": {
33 "editable": self._get_value_vmware_attributes()
34 }
35 },
36 nodes_kwargs=[{
37 "hostname": "controller-node",
38 "status": consts.NODE_STATUSES.ready
39 }]
40 )
41 self.ready_compute_node = self.env.create_node(
42 hostname="node-1",
43 name="Node 1",
44 roles=["compute-vmware"],
45 status=consts.NODE_STATUSES.ready,
46 cluster_id=self.cluster.id
47 )
48
49 def _get_target_id(self, nova_compute):
50 return nova_compute["target_node"]["current"]["id"]
51
52 def _get_default_nova_computes(self):
53 return [
54 {
55 "datastore_regex": ".*",
56 "vsphere_cluster": "Cluster1",
57 "target_node": {
58 "current": {
59 "id": "node-1",
60 "label": "node-1"
61 }
62 },
63 "service_name": "ns1"
64 },
65 {
66 "datastore_regex": ".*",
67 "vsphere_cluster": "Cluster0",
68 "target_node": {
69 "current": {
70 "id": "controllers",
71 "label": "controllers"
72 }
73 },
74 "service_name": "ns0"
75 }
76 ]
77
78 def _get_value_vmware_attributes(self, nova_computes=None):
79 return {
80 "value": {
81 "availability_zones": [{
82 "vcenter_username": "admin",
83 "az_name": "vcenter",
84 "vcenter_password": "pass",
85 "vcenter_host": "172.16.0.254",
86 "nova_computes":
87 nova_computes or self._get_default_nova_computes()
88 }]
89 }
90 }
91
92 def validate_nova_compute_raises_regexp(self, nova_computes, error_msg):
93 with self.assertRaisesRegexp(errors.InvalidData, error_msg):
94 VmwareAttributesValidator._validate_nova_computes(
95 {"editable": self._get_value_vmware_attributes(nova_computes)},
96 self.cluster.vmware_attributes
97 )
98
99 def test_change_exist_nova_compute(self):
100 nova_computes = self._get_default_nova_computes()
101 changed_attribute = 'vsphere_cluster'
102 for nc in nova_computes:
103 if self._get_target_id(nc) == self.ready_compute_node.hostname:
104 nc[changed_attribute] = "ClusterXX"
105 break
106
107 self.validate_nova_compute_raises_regexp(
108 nova_computes,
109 "Parameter '{0}' of nova compute instance with target node '{1}' "
110 "couldn't be changed".format(
111 changed_attribute, self.ready_compute_node.name
112 )
113 )
114
115 def test_delete_operational_nova_compute_node(self):
116 nova_computes = [
117 nc for nc in self._get_default_nova_computes() if
118 self._get_target_id(nc) != self.ready_compute_node.hostname
119 ]
120 self.validate_nova_compute_raises_regexp(
121 nova_computes,
122 "The following compute-vmware node couldn't be deleted from "
123 "vSphere cluster: {0}".format(self.ready_compute_node.name)
124 )
125
126 def test_duplicate_values_for_nova_computes(self):
127 for attr in ("vsphere_cluster", "target_node", "service_name"):
128 exist_nova_computes = self._get_default_nova_computes()
129 duplicate_value = exist_nova_computes[0][attr]
130 new_nova_compute = {
131 "datastore_regex": ".*",
132 "vsphere_cluster": "ClusterXX",
133 "target_node": {
134 "current": {
135 "id": "node-X",
136 "label": "node-X"
137 },
138 },
139 "service_name": "nsXX"
140 }
141 new_nova_compute.update({attr: duplicate_value})
142 exist_nova_computes.append(new_nova_compute)
143 duplicate_value = duplicate_value if attr != "target_node" \
144 else duplicate_value["current"]["id"]
145
146 self.validate_nova_compute_raises_regexp(
147 exist_nova_computes,
148 "Duplicate value '{0}' for attribute '{1}' is not allowed".
149 format(duplicate_value, attr)
150 )
151
152 def test_empty_values_for_nova_computes(self):
153 nova_computes = self._get_default_nova_computes()
154 nova_computes[0]["vsphere_cluster"] = ""
155 self.validate_nova_compute_raises_regexp(
156 nova_computes,
157 "Empty value for attribute 'vsphere_cluster' is not allowed"
158 )
159
160 def test_nova_compute_setting_validate_pass(self):
161 new_compute_vmware_node = self.env.create_node(
162 hostname="node-2",
163 name="Node 2",
164 pending_roles=["compute-vmware"],
165 pending_addition=True,
166 cluster_id=self.cluster.id
167 )
168 self.env.create_node(
169 hostname="node-3",
170 name="Node 3",
171 roles=["compute-vmware"],
172 pending_deletion=True,
173 cluster_id=self.cluster.id
174 )
175 attributes = self.cluster.vmware_attributes
176 new_nova_computes = self._get_default_nova_computes()
177 new_nova_computes.extend([{
178 "datastore_regex": ".*",
179 "vsphere_cluster": "Cluster2",
180 "target_node": {
181 "current": {
182 "id": new_compute_vmware_node.hostname,
183 "label": new_compute_vmware_node.name
184 }
185 },
186 "service_name": "ns2"
187 }])
188 self.assertNotRaises(errors.InvalidData,
189 VmwareAttributesValidator._validate_nova_computes,
190 {"editable": self._get_value_vmware_attributes(
191 new_nova_computes)},
192 attributes)
193
194 def test_change_controller_nova_computes_pass(self):
195 cluster = self.env.create(
196 cluster_kwargs={
197 "api": False,
198 "status": consts.CLUSTER_STATUSES.new,
199 "vmware_attributes": {
200 "editable": self._get_value_vmware_attributes()
201 }
202 }
203 )
204 new_nova_computes = [nc for nc in self._get_default_nova_computes()
205 if self._get_target_id(nc) == "controllers"]
206 new_nova_computes[0]["vsphere_cluster"] = "new vsphere name"
207 new_nova_computes.append({
208 "datastore_regex": ".*",
209 "vsphere_cluster": "Cluster10",
210 "target_node": {
211 "current": {
212 "id": "controllers",
213 "label": "controllers"
214 }
215 },
216 "service_name": "ns10"
217 })
218 self.assertNotRaises(errors.InvalidData,
219 VmwareAttributesValidator._validate_nova_computes,
220 {"editable": self._get_value_vmware_attributes(
221 new_nova_computes)},
222 cluster.vmware_attributes)
223
224 @patch("nailgun.db.sqlalchemy.models.Cluster.is_locked", return_value=True)
225 def test_change_controllers_nova_compute_setting(self, lock_mock):
226 new_nova_computes = self._get_default_nova_computes()
227 changed_vsphere_cluster = None
228 changed_attribute = "service_name"
229 for nc in new_nova_computes:
230 if self._get_target_id(nc) == "controllers":
231 nc[changed_attribute] = "new_service_name"
232 changed_vsphere_cluster = nc
233 break
234
235 self.validate_nova_compute_raises_regexp(
236 new_nova_computes,
237 "Parameter '{0}' of nova compute instance with vSphere cluster "
238 "name '{1}' couldn't be changed".format(
239 changed_attribute, changed_vsphere_cluster["vsphere_cluster"])
240 )
241
242 @patch("nailgun.db.sqlalchemy.models.Cluster.is_locked", return_value=True)
243 def test_add_controllers_nova_compute_setting(self, lock_mock):
244 new_nova_computes = self._get_default_nova_computes()
245 new_nova_computes.extend([{
246 "datastore_regex": ".*",
247 "vsphere_cluster": "Cluster20",
248 "target_node": {
249 "current": {
250 "id": "controllers",
251 "label": "controllers"
252 }
253 },
254 "service_name": "ns20"
255 }, {
256 "datastore_regex": ".*",
257 "vsphere_cluster": "Cluster30",
258 "target_node": {
259 "current": {
260 "id": "controllers",
261 "label": "controllers"
262 }
263 },
264 "service_name": "ns30"
265 }])
266 self.validate_nova_compute_raises_regexp(
267 new_nova_computes,
268 "Nova compute instances with target 'controllers' couldn't be "
269 "added to operational environment. Check nova compute instances "
270 "with the following vSphere cluster names: {0}".format(
271 ", ".join(sorted(["Cluster30", "Cluster20"]))
272 )
273 )
274