def test_networks_set_no_default_network(self):
     roles = [
         {'name': 'Compute',
          'defaults': {
              'networks': [
                  {'network': 'some_net', 'vif': True},
              ]}
          },
         {'name': 'Controller',
          'defaults': {
              'networks': [
                  {'network': 'some_net', 'vif': True},
              ]}
          },
     ]
     instances, environment, role_net_map, hostname_role_map = bd.expand(
         roles, 'overcloud', True, self.default_image, None
     )
     self.assertEqual(
         [
             {'hostname': 'overcloud-novacompute-0',
              'image': {'href': 'overcloud-full'},
              'networks': [{'network': 'some_net', 'vif': True}],
              'nics': [{'network': 'some_net'}],
              'config_drive': {'meta_data': {'instance-type': 'Compute'}}},
             {'hostname': 'overcloud-controller-0',
              'image': {'href': 'overcloud-full'},
              'networks': [{'network': 'some_net', 'vif': True}],
              'nics': [{'network': 'some_net'}],
              'config_drive': {'meta_data': {'instance-type': 'Controller'}}},
         ],
         instances)
     self.assertEqual({'overcloud-controller-0': 'Controller',
                       'overcloud-novacompute-0': 'Compute'},
                      hostname_role_map)
 def test_instances_without_hostname(self):
     roles = [{
         'name': 'Compute',
         'count': 2,
         'defaults': {
             'profile': 'compute'
         },
         'hostname_format': 'compute-%index%.example.com'
     }, {
         'name': 'Controller',
         'count': 2,
         'defaults': {
             'profile': 'control'
         },
         'instances': [{
             'profile': 'control-X'
             # missing hostname here
         }, {
             'name': 'node-0',
             'traits': ['CUSTOM_FOO'],
             'nics': [{'subnet': 'leaf-2'}]},
         ]},
     ]
     instances, environment, role_net_map, hostname_role_map = bd.expand(
         roles, 'overcloud', True, self.default_image
     )
     self.assertEqual(
         [
             {'hostname': 'compute-0.example.com',
              'capabilities': {'profile': 'compute'},
              'image': {'href': 'overcloud-full'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Compute'}}},
             {'hostname': 'compute-1.example.com',
              'capabilities': {'profile': 'compute'},
              'image': {'href': 'overcloud-full'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Compute'}}},
             {'hostname': 'overcloud-controller-0',
              'capabilities': {'profile': 'control-X'},
              'image': {'href': 'overcloud-full'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
             # Name provides the default for hostname
             {'name': 'node-0', 'capabilities': {'profile': 'control'},
              'hostname': 'node-0',
              'image': {'href': 'overcloud-full'},
              'traits': ['CUSTOM_FOO'], 'nics': [{'subnet': 'leaf-2'}],
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
         ],
         instances)
     self.assertEqual({'compute-0.example.com': 'Compute',
                       'compute-1.example.com': 'Compute',
                       'node-0': 'Controller',
                       'overcloud-controller-0': 'Controller'},
                      hostname_role_map)
 def test_networks_nics_are_mutually_exclusive(self):
     # Neither 'nics' nor 'networks' - OK
     roles = [{'name': 'Compute', 'defaults': {}}]
     bd.expand(roles, 'overcloud', True, self.default_image)
     # 'networks' but not 'nics' - OK
     roles = [{'name': 'Compute', 'defaults': {'networks': []}}]
     bd.expand(roles, 'overcloud', True, self.default_image)
     # 'nics' but not 'networks' - OK
     roles = [{'name': 'Compute', 'defaults': {'nics': []}}]
     bd.expand(roles, 'overcloud', True, self.default_image)
     # 'networks' and 'nics' - mutually exclusive, Raises ValidationError
     roles = [{'name': 'Compute', 'defaults': {'networks': [], 'nics': []}}]
     self.assertRaises(
         jsonschema.exceptions.ValidationError,
         bd.expand, roles, 'overcloud', True, self.default_image)
 def test_image_in_defaults(self):
     roles = [{
         'name': 'Controller',
         'defaults': {
             'image': {
                 'href': 'file:///tmp/foo.qcow2',
                 'checksum': '12345678'
             }
         },
         'count': 3,
         'instances': [{
             'hostname': 'overcloud-controller-0',
             'image': {'href': 'overcloud-full'}
         }, {
             'hostname': 'overcloud-controller-1',
         }]
     }]
     instances, environment, role_net_map, hostname_role_map = bd.expand(
         roles, 'overcloud', True, self.default_image
     )
     self.assertEqual(
         [
             {'hostname': 'overcloud-controller-0',
              'image': {'href': 'overcloud-full'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
             {'hostname': 'overcloud-controller-1',
              'image': {'href': 'file:///tmp/foo.qcow2',
                        'checksum': '12345678'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
             {'hostname': 'overcloud-controller-2',
              'image': {'href': 'file:///tmp/foo.qcow2',
                        'checksum': '12345678'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
         ],
         instances)
    def test_simple(self):
        roles = [
            {'name': 'Compute'},
            {'name': 'Controller'},
        ]
        instances, environment, role_net_map, hostname_role_map = bd.expand(
            roles, 'overcloud', True, self.default_image
        )

        self.assertEqual(
            [
                {'hostname': 'overcloud-novacompute-0',
                 'image': {'href': 'overcloud-full'},
                 'config_drive': {'meta_data': {
                     'instance-type': 'Compute'}}},
                {'hostname': 'overcloud-controller-0',
                 'image': {'href': 'overcloud-full'},
                 'config_drive': {'meta_data': {
                     'instance-type': 'Controller'}}},
            ],
            instances)
        self.assertEqual(
            {
                'ComputeHostnameFormat':
                '%stackname%-novacompute-%index%',
                'ComputeCount': 1,
                'ControllerHostnameFormat':
                '%stackname%-controller-%index%',
                'ControllerCount': 1,
                'HostnameMap': {
                    'overcloud-novacompute-0': 'overcloud-novacompute-0',
                    'overcloud-controller-0': 'overcloud-controller-0'
                }
            },
            environment['parameter_defaults'])
        self.assertEqual({'overcloud-controller-0': 'Controller',
                          'overcloud-novacompute-0': 'Compute'},
                         hostname_role_map)
    def test_unprovisioned_no_hostname(self):
        roles = [{
            'name': 'Controller',
            'defaults': {
                'profile': 'control',
            },
            'count': 2,
            'instances': [{
                'name': 'node-0',
            }, {
                'name': 'node-1',
                'provisioned': False
            }, {
                'name': 'node-2',
                'provisioned': False
            }, {
                'name': 'node-3',
                'provisioned': True
            }]
        }]
        instances, environment, role_net_map, hostname_role_map = bd.expand(
            roles, 'overcloud', True, self.default_image
        )
        self.assertEqual([
            {
                'hostname': 'node-0',
                'name': 'node-0',
                'capabilities': {'profile': 'control'},
                'image': {'href': 'overcloud-full'},
                'config_drive': {'meta_data': {'instance-type': 'Controller'}}
            }, {
                'hostname': 'node-3',
                'name': 'node-3',
                'capabilities': {'profile': 'control'},
                'image': {'href': 'overcloud-full'},
                'config_drive': {'meta_data': {'instance-type': 'Controller'}}
            }],
            instances)
        self.assertEqual({
            'ControllerCount': 2,
            'ControllerRemovalPolicies': [
                {'resource_list': [1, 2]}
            ],
            'ControllerHostnameFormat':
                '%stackname%-controller-%index%',
            'HostnameMap': {
                'overcloud-controller-0': 'node-0',
                'overcloud-controller-1': 'node-1',
                'overcloud-controller-2': 'node-2',
                'overcloud-controller-3': 'node-3'}
            },
            environment['parameter_defaults'])
        self.assertEqual({'node-0': 'Controller', 'node-3': 'Controller'},
                         hostname_role_map)

        instances, environment, role_net_map, hostname_role_map = bd.expand(
            roles, 'overcloud', False, self.default_image
        )
        self.assertEqual([
            {
                'hostname': 'node-1',
                'name': 'node-1',
                'capabilities': {'profile': 'control'},
                'image': {'href': 'overcloud-full'},
                'config_drive': {'meta_data': {'instance-type': 'Controller'}}
            }, {
                'hostname': 'node-2',
                'name': 'node-2',
                'capabilities': {'profile': 'control'},
                'image': {'href': 'overcloud-full'},
                'config_drive': {'meta_data': {'instance-type': 'Controller'}}
            }],
            instances)
        self.assertEqual({}, environment)
        self.assertEqual({'node-1': 'Controller', 'node-2': 'Controller'},
                         hostname_role_map)
 def test_count_with_instances(self):
     roles = [{
         'name': 'Compute',
         'count': 2,
         'defaults': {
             'profile': 'compute',
         },
         'hostname_format': 'compute-%index%.example.com'
     }, {
         'name': 'Controller',
         'defaults': {
             'profile': 'control',
         },
         'count': 3,
         'instances': [{
             'hostname': 'controller-X.example.com',
             'profile': 'control-X'
         }, {
             'name': 'node-0',
             'traits': ['CUSTOM_FOO'],
             'nics': [{'subnet': 'leaf-2'}]},
         ]},
     ]
     instances, environment, role_net_map, hostname_role_map = bd.expand(
         roles, 'overcloud', True, self.default_image
     )
     self.assertEqual([
         {
             'hostname': 'compute-0.example.com',
             'capabilities': {'profile': 'compute'},
             'image': {'href': 'overcloud-full'},
             'config_drive': {'meta_data': {'instance-type': 'Compute'}}
         }, {
             'hostname': 'compute-1.example.com',
             'capabilities': {'profile': 'compute'},
             'image': {'href': 'overcloud-full'},
             'config_drive': {'meta_data': {'instance-type': 'Compute'}}
         }, {
             'hostname': 'controller-X.example.com',
             'capabilities': {'profile': 'control-X'},
             'image': {'href': 'overcloud-full'},
             'config_drive': {'meta_data': {'instance-type': 'Controller'}}
         }, {
             'hostname': 'node-0',
             'name': 'node-0',
             'nics': [{'subnet': 'leaf-2'}],
             'capabilities': {'profile': 'control'},
             'traits': ['CUSTOM_FOO'],
             'image': {'href': 'overcloud-full'},
             'config_drive': {'meta_data': {'instance-type': 'Controller'}}
         }, {
             'hostname': 'overcloud-controller-2',
             'capabilities': {'profile': 'control'},
             'image': {'href': 'overcloud-full'},
             'config_drive': {'meta_data': {'instance-type': 'Controller'}}
         }],
         instances)
     self.assertEqual({
         'ComputeCount': 2,
         'ComputeHostnameFormat':
             'compute-%index%.example.com',
         'ControllerCount': 3,
         'ControllerHostnameFormat':
             '%stackname%-controller-%index%',
         'HostnameMap': {
             'compute-0.example.com': 'compute-0.example.com',
             'compute-1.example.com': 'compute-1.example.com',
             'overcloud-controller-0': 'controller-X.example.com',
             'overcloud-controller-1': 'node-0',
             'overcloud-controller-2': 'overcloud-controller-2'}
         },
         environment['parameter_defaults'])
     self.assertEqual({'compute-0.example.com': 'Compute',
                       'compute-1.example.com': 'Compute',
                       'controller-X.example.com': 'Controller',
                       'node-0': 'Controller',
                       'overcloud-controller-2': 'Controller'},
                      hostname_role_map)
 def test_explicit_instances(self):
     roles = [{
         'name': 'Compute',
         'count': 2,
         'defaults': {
             'profile': 'compute'
         },
         'hostname_format': 'compute-%index%.example.com'
     }, {
         'name': 'Controller',
         'count': 2,
         'defaults': {
             'profile': 'control',
             'networks': [
                 {'network': 'foo', 'subnet': 'foo_subnet'},
             ]
         },
         'instances': [{
             'hostname': 'controller-X.example.com',
             'profile': 'control-X',
             'networks': [
                 {'network': 'inst_net', 'fixed_ip': '10.1.1.1'}
             ],
             'config_drive': {
                 'meta_data': {'foo': 'bar'}
             }
         }, {
             'name': 'node-0',
             'traits': ['CUSTOM_FOO'],
             'networks': [{'network': 'some_net', 'subnet': 'leaf-2',
                           'vif': True}],
             'config_drive': {
                 'cloud_config': {'bootcmd': ['echo hi']}
             }
         }]},
     ]
     instances, environment, role_net_map, hostname_role_map = bd.expand(
         roles, 'overcloud', True, self.default_image
     )
     self.assertEqual(
         [
             {'hostname': 'compute-0.example.com',
              'capabilities': {'profile': 'compute'},
              'image': {'href': 'overcloud-full'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Compute'}}},
             {'hostname': 'compute-1.example.com',
              'capabilities': {'profile': 'compute'},
              'image': {'href': 'overcloud-full'},
              'config_drive': {'meta_data': {
                  'instance-type': 'Compute'}}},
             {'hostname': 'controller-X.example.com',
              'image': {'href': 'overcloud-full'},
              'capabilities': {'profile': 'control-X'},
              'networks': [{'fixed_ip': '10.1.1.1', 'network': 'inst_net'},
                           {'network': 'foo', 'subnet': 'foo_subnet'}],
              'config_drive': {'meta_data': {
                  'foo': 'bar',
                  'instance-type': 'Controller'}},
              },
             # Name provides the default for hostname later on.
             {'name': 'node-0',
              'capabilities': {'profile': 'control'},
              'hostname': 'node-0',
              'networks': [
                  {'network': 'some_net', 'subnet': 'leaf-2', 'vif': True},
                  {'network': 'foo', 'subnet': 'foo_subnet'},
              ],
              'image': {'href': 'overcloud-full'},
              'traits': ['CUSTOM_FOO'],
              'nics': [{'network': 'some_net', 'subnet': 'leaf-2'}],
              'config_drive': {
                  'cloud_config': {'bootcmd': ['echo hi']},
                  'meta_data': {'instance-type': 'Controller'}
              }},
         ],
         instances)
     self.assertEqual(
         {
             'ComputeHostnameFormat':
             'compute-%index%.example.com',
             'ComputeCount': 2,
             'ControllerHostnameFormat':
             '%stackname%-controller-%index%',
             'ControllerCount': 2,
             'HostnameMap': {
                 'compute-0.example.com': 'compute-0.example.com',
                 'compute-1.example.com': 'compute-1.example.com',
                 'overcloud-controller-0': 'controller-X.example.com',
                 'overcloud-controller-1': 'node-0',
             }
         },
         environment['parameter_defaults'])
     self.assertEqual({'compute-0.example.com': 'Compute',
                       'compute-1.example.com': 'Compute',
                       'controller-X.example.com': 'Controller',
                       'node-0': 'Controller'},
                      hostname_role_map)
 def test_with_parameters(self):
     roles = [{
         'name': 'Compute',
         'count': 2,
         'defaults': {
             'profile': 'compute'
         },
         'hostname_format': 'compute-%index%.example.com'
     }, {
         'name': 'Controller',
         'count': 3,
         'defaults': {
             'profile': 'control'
         },
         'hostname_format': 'controller-%index%.example.com'
     }]
     instances, environment, role_net_map, hostname_role_map = bd.expand(
         roles, 'overcloud', True, self.default_image,
         user_name='heat-admin', ssh_public_keys='aaaa'
     )
     self.assertEqual(
         [
             {'hostname': 'compute-0.example.com',
              'capabilities': {'profile': 'compute'},
              'image': {'href': 'overcloud-full'},
              'ssh_public_keys': 'aaaa',
              'user_name': 'heat-admin',
              'config_drive': {'meta_data': {
                  'instance-type': 'Compute'}}},
             {'hostname': 'compute-1.example.com',
              'capabilities': {'profile': 'compute'},
              'image': {'href': 'overcloud-full'},
              'ssh_public_keys': 'aaaa',
              'user_name': 'heat-admin',
              'config_drive': {'meta_data': {
                  'instance-type': 'Compute'}}},
             {'hostname': 'controller-0.example.com',
              'capabilities': {'profile': 'control'},
              'image': {'href': 'overcloud-full'},
              'ssh_public_keys': 'aaaa',
              'user_name': 'heat-admin',
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
             {'hostname': 'controller-1.example.com',
              'capabilities': {'profile': 'control'},
              'image': {'href': 'overcloud-full'},
              'ssh_public_keys': 'aaaa',
              'user_name': 'heat-admin',
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
             {'hostname': 'controller-2.example.com',
              'capabilities': {'profile': 'control'},
              'image': {'href': 'overcloud-full'},
              'ssh_public_keys': 'aaaa',
              'user_name': 'heat-admin',
              'config_drive': {'meta_data': {
                  'instance-type': 'Controller'}}},
         ],
         instances)
     self.assertEqual(
         {
             'ComputeHostnameFormat':
             'compute-%index%.example.com',
             'ComputeCount': 2,
             'ControllerHostnameFormat':
             'controller-%index%.example.com',
             'ControllerCount': 3,
             'HostnameMap': {
                 'compute-0.example.com': 'compute-0.example.com',
                 'compute-1.example.com': 'compute-1.example.com',
                 'controller-0.example.com': 'controller-0.example.com',
                 'controller-1.example.com': 'controller-1.example.com',
                 'controller-2.example.com': 'controller-2.example.com',
             }
         },
         environment['parameter_defaults'])
     self.assertEqual({'compute-0.example.com': 'Compute',
                       'compute-1.example.com': 'Compute',
                       'controller-0.example.com': 'Controller',
                       'controller-1.example.com': 'Controller',
                       'controller-2.example.com': 'Controller'},
                      hostname_role_map)