Example #1
0
    def serialize_node(cls, cluster_attrs, node):
        """Serialize a single node."""

        serialized_node = {
            'uid': node.uid,
            'power_address': node.ip,
            'name': TaskHelper.make_slave_name(node.id),
            # right now it duplicates to avoid possible issues
            'slave_name': TaskHelper.make_slave_name(node.id),
            'hostname': node.fqdn,
            'power_pass': cls.get_ssh_key_path(node),
            'profile': cluster_attrs['cobbler']['profile'],
            'power_type': 'ssh',
            'power_user': '******',
            'name_servers': '\"%s\"' % settings.DNS_SERVERS,
            'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
            'netboot_enabled': '1',
            # For provisioning phase
            'kernel_options': {
                'netcfg/choose_interface': node.admin_interface.mac,
                'udevrules': cls.interfaces_mapping_for_udev(node)
            },
            'ks_meta': {
                'pm_data': {
                    'ks_spaces': node.attributes.volumes,
                    'kernel_params': node.kernel_params
                },
                'fuel_version': node.cluster.fuel_version,
                'puppet_auto_setup': 1,
                'puppet_master': settings.PUPPET_MASTER_HOST,
                'puppet_enable': 0,
                'mco_auto_setup': 1,
                'install_log_2_syslog': 1,
                'mco_pskey': settings.MCO_PSKEY,
                'mco_vhost': settings.MCO_VHOST,
                'mco_host': settings.MCO_HOST,
                'mco_user': settings.MCO_USER,
                'mco_password': settings.MCO_PASSWORD,
                'mco_connector': settings.MCO_CONNECTOR,
                'mco_enable': 1,
                'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', '')
            }
        }

        orchestrator_data = objects.Release.get_orchestrator_data_dict(
            node.cluster.release)
        if orchestrator_data:
            serialized_node['ks_meta']['repo_metadata'] = \
                orchestrator_data['repo_metadata']

        vlan_splinters = cluster_attrs.get('vlan_splinters', None)
        if vlan_splinters == 'kernel_lt':
            serialized_node['ks_meta']['kernel_lt'] = 1

        serialized_node.update(cls.serialize_interfaces(node))

        return serialized_node
    def serialize_node(cls, cluster_attrs, node):
        """Serialize a single node."""

        serialized_node = {
            'uid': node.uid,
            'power_address': node.ip,
            'name': TaskHelper.make_slave_name(node.id),
            # right now it duplicates to avoid possible issues
            'slave_name': TaskHelper.make_slave_name(node.id),
            'hostname': node.fqdn,
            'power_pass': cls.get_ssh_key_path(node),

            'profile': cluster_attrs['cobbler']['profile'],
            'power_type': 'ssh',
            'power_user': '******',
            'name_servers': '\"%s\"' % settings.DNS_SERVERS,
            'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
            'netboot_enabled': '1',
            # For provisioning phase
            'kernel_options': {
                'netcfg/choose_interface': node.admin_interface.mac,
                'udevrules': cls.interfaces_mapping_for_udev(node)},
            'ks_meta': {
                'pm_data': {
                    'ks_spaces': node.attributes.volumes,
                    'kernel_params': node.kernel_params},
                'fuel_version': node.cluster.fuel_version,
                'puppet_auto_setup': 1,
                'puppet_master': settings.PUPPET_MASTER_HOST,
                'puppet_enable': 0,
                'mco_auto_setup': 1,
                'install_log_2_syslog': 1,
                'mco_pskey': settings.MCO_PSKEY,
                'mco_vhost': settings.MCO_VHOST,
                'mco_host': settings.MCO_HOST,
                'mco_user': settings.MCO_USER,
                'mco_password': settings.MCO_PASSWORD,
                'mco_connector': settings.MCO_CONNECTOR,
                'mco_enable': 1,
                'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', '')}}

        orchestrator_data = objects.Release.get_orchestrator_data_dict(
            node.cluster.release)
        if orchestrator_data:
            serialized_node['ks_meta']['repo_metadata'] = \
                orchestrator_data['repo_metadata']

        vlan_splinters = cluster_attrs.get('vlan_splinters', None)
        if vlan_splinters == 'kernel_lt':
            serialized_node['ks_meta']['kernel_lt'] = 1

        serialized_node.update(cls.serialize_interfaces(node))

        return serialized_node
Example #3
0
    def node_list(cls, nodes):
        """Generate nodes list. Represents
        as "nodes" parameter in facts.
        """
        node_list = []

        for node in nodes:
            network_data = node.network_data

            for role in set(node.pending_roles + node.roles):
                node_list.append({
                    # Yes, uid is really should be a string
                    'uid': str(node.id),
                    'fqdn': node.fqdn,
                    'name': TaskHelper.make_slave_name(node.id),
                    'role': role,

                    # Addresses
                    'internal_address': cls.get_addr(network_data,
                                                     'management')['ip'],
                    'internal_netmask': cls.get_addr(network_data,
                                                     'management')['netmask'],
                    'storage_address': cls.get_addr(network_data,
                                                    'storage')['ip'],
                    'storage_netmask': cls.get_addr(network_data,
                                                    'storage')['netmask'],
                    'public_address': cls.get_addr(network_data,
                                                   'public')['ip'],
                    'public_netmask': cls.get_addr(network_data,
                                                   'public')['netmask']})

        return node_list
Example #4
0
    def node_list(cls, nodes):
        """Generate nodes list. Represents
        as "nodes" parameter in facts.
        """
        node_list = []

        for node in nodes:
            network_data = node.network_data

            for role in node.all_roles:
                node_list.append({
                    # Yes, uid is really should be a string
                    'uid': str(node.id),
                    'fqdn': node.fqdn,
                    'name': TaskHelper.make_slave_name(node.id),
                    'role': role,

                    # Addresses
                    'internal_address': cls.get_addr(network_data,
                                                     'management')['ip'],
                    'internal_netmask': cls.get_addr(network_data,
                                                     'management')['netmask'],
                    'storage_address': cls.get_addr(network_data,
                                                    'storage')['ip'],
                    'storage_netmask': cls.get_addr(network_data,
                                                    'storage')['netmask'],
                    'public_address': cls.get_addr(network_data,
                                                   'public')['ip'],
                    'public_netmask': cls.get_addr(network_data,
                                                   'public')['netmask']})

        return node_list
Example #5
0
    def serialize_node(cls, cluster_attrs, node):
        """Serialize a single node."""

        serialized_node = {
            'power_address': node.ip,
            'name': TaskHelper.make_slave_name(node.id),
            'hostname': node.fqdn,
            'power_pass': cls.get_ssh_key_path(node),

            'profile': cluster_attrs['cobbler']['profile'],
            'power_type': 'ssh',
            'power_user': '******',
            'name_servers': '\"%s\"' % settings.DNS_SERVERS,
            'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
            'netboot_enabled': '1',
            'ks_meta': {
                'ks_spaces': node.attributes.volumes,
                'puppet_auto_setup': 1,
                'puppet_master': settings.PUPPET_MASTER_HOST,
                'puppet_version': settings.PUPPET_VERSION,
                'puppet_enable': 0,
                'mco_auto_setup': 1,
                'install_log_2_syslog': 1,
                'mco_pskey': settings.MCO_PSKEY,
                'mco_vhost': settings.MCO_VHOST,
                'mco_host': settings.MCO_HOST,
                'mco_user': settings.MCO_USER,
                'mco_password': settings.MCO_PASSWORD,
                'mco_connector': settings.MCO_CONNECTOR,
                'mco_enable': 1,
                'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', '')}}

        serialized_node.update(cls.serialize_interfaces(node))

        return serialized_node
Example #6
0
 def message(cls, task, deploy_task):
     nodes_to_stop = db().query(Node).filter(
         Node.cluster_id == task.cluster.id
     ).filter(
         not_(Node.status == 'ready')
     ).yield_per(100)
     return {
         "method": "stop_deploy_task",
         "respond_to": "stop_deployment_resp",
         "args": {
             "task_uuid": task.uuid,
             "stop_task_uuid": deploy_task.uuid,
             "nodes": [
                 {
                     'uid': n.uid,
                     'roles': n.roles,
                     'slave_name': TaskHelper.make_slave_name(n.id)
                 } for n in nodes_to_stop
             ],
             "engine": {
                 "url": settings.COBBLER_URL,
                 "username": settings.COBBLER_USER,
                 "password": settings.COBBLER_PASSWORD,
             }
         }
     }
    def serialize_node(cls, cluster_attrs, node):
        """Serialize a single node."""

        serialized_node = {
            'power_address': node.ip,
            'name': TaskHelper.make_slave_name(node.id),
            'hostname': node.fqdn,
            'power_pass': cls.get_ssh_key_path(node),

            'profile': cluster_attrs['cobbler']['profile'],
            'power_type': 'ssh',
            'power_user': '******',
            'name_servers': '\"%s\"' % settings.DNS_SERVERS,
            'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
            'netboot_enabled': '1',
            'ks_meta': {
                'ks_spaces': node.attributes.volumes,
                'puppet_auto_setup': 1,
                'puppet_master': settings.PUPPET_MASTER_HOST,
                'puppet_version': settings.PUPPET_VERSION,
                'puppet_enable': 0,
                'mco_auto_setup': 1,
                'install_log_2_syslog': 1,
                'mco_pskey': settings.MCO_PSKEY,
                'mco_vhost': settings.MCO_VHOST,
                'mco_host': settings.MCO_HOST,
                'mco_user': settings.MCO_USER,
                'mco_password': settings.MCO_PASSWORD,
                'mco_connector': settings.MCO_CONNECTOR,
                'mco_enable': 1,
                'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', '')}}

        serialized_node.update(cls.serialize_interfaces(node))

        return serialized_node
Example #8
0
 def message(cls, task, stop_task):
     nodes_to_stop = db().query(Node).filter(
         Node.cluster_id == task.cluster.id).filter(
             not_(Node.status == 'ready')).yield_per(100)
     return make_astute_message(
         "stop_deploy_task", "stop_deployment_resp", {
             "task_uuid":
             task.uuid,
             "stop_task_uuid":
             stop_task.uuid,
             "nodes": [{
                 'uid':
                 n.uid,
                 'roles':
                 n.roles,
                 'slave_name':
                 TaskHelper.make_slave_name(n.id),
                 'admin_ip':
                 objects.Node.get_network_manager(n).get_admin_ip_for_node(
                     n)
             } for n in nodes_to_stop],
             "engine": {
                 "url": settings.COBBLER_URL,
                 "username": settings.COBBLER_USER,
                 "password": settings.COBBLER_PASSWORD,
                 "master_ip": settings.MASTER_IP,
             }
         })
    def test_deploy_and_remove_correct_nodes_and_statuses(self, mocked_rpc):
        self.env.create(
            cluster_kwargs={},
            nodes_kwargs=[
                {
                    "pending_addition": True,
                },
                {
                    "status": "error",
                    "pending_deletion": True
                }
            ]
        )
        self.env.launch_deployment()

        # launch_deployment kicks ClusterChangesHandler
        # which in turns launches DeploymentTaskManager
        # which runs DeletionTask, ProvisionTask and DeploymentTask.
        # DeletionTask is sent to one orchestrator worker and
        # ProvisionTask and DeploymentTask messages are sent to
        # another orchestrator worker.
        # That is why we expect here list of two sets of
        # arguments in mocked nailgun.rpc.cast
        # The first set of args is for deletion task and
        # the second one is for provisioning and deployment.

        # remove_nodes method call [0][0][1]
        n_rpc_remove = nailgun.task.task.rpc.cast. \
            call_args_list[0][0][1]['args']['nodes']
        self.assertEquals(len(n_rpc_remove), 1)
        self.assertEquals(n_rpc_remove[0]['uid'], self.env.nodes[1].id)

        # provision method call [1][0][1][0]
        n_rpc_provision = nailgun.task.manager.rpc.cast. \
            call_args_list[1][0][1][0]['args']['nodes']
        # Nodes will be appended in provision list if
        # they 'pending_deletion' = False and
        # 'status' in ('discover', 'provisioning') or
        # 'status' = 'error' and 'error_type' = 'provision'
        # So, only one node from our list will be appended to
        # provision list.
        self.assertEquals(len(n_rpc_provision), 1)
        self.assertEquals(
            n_rpc_provision[0]['name'],
            TaskHelper.make_slave_name(self.env.nodes[0].id,
                                       self.env.nodes[0].role)
        )

        # deploy method call [1][0][1][1]
        n_rpc_deploy = nailgun.task.manager.rpc.cast. \
            call_args_list[1][0][1][1]['args']['nodes']
        self.assertEquals(len(n_rpc_deploy), 1)
        self.assertEquals(n_rpc_deploy[0]['uid'], self.env.nodes[0].id)
    def test_deploy_and_remove_correct_nodes_and_statuses(self, mocked_rpc):
        self.env.create(
            cluster_kwargs={},
            nodes_kwargs=[
                {
                    "pending_addition": True,
                },
                {
                    "status": "error",
                    "pending_deletion": True
                }
            ]
        )
        self.env.launch_deployment()

        # launch_deployment kicks ClusterChangesHandler
        # which in turns launches DeploymentTaskManager
        # which runs DeletionTask, ProvisionTask and DeploymentTask.
        # DeletionTask is sent to one orchestrator worker and
        # ProvisionTask and DeploymentTask messages are sent to
        # another orchestrator worker.
        # That is why we expect here list of two sets of
        # arguments in mocked nailgun.rpc.cast
        # The first set of args is for deletion task and
        # the second one is for provisioning and deployment.

        # remove_nodes method call [0][0][1]
        n_rpc_remove = nailgun.task.task.rpc.cast. \
            call_args_list[0][0][1]['args']['nodes']
        self.assertEquals(len(n_rpc_remove), 1)
        self.assertEquals(n_rpc_remove[0]['uid'], self.env.nodes[1].id)

        # provision method call [1][0][1][0]
        n_rpc_provision = nailgun.task.manager.rpc.cast. \
            call_args_list[1][0][1][0]['args']['nodes']
        # Nodes will be appended in provision list if
        # they 'pending_deletion' = False and
        # 'status' in ('discover', 'provisioning') or
        # 'status' = 'error' and 'error_type' = 'provision'
        # So, only one node from our list will be appended to
        # provision list.
        self.assertEquals(len(n_rpc_provision), 1)
        self.assertEquals(
            n_rpc_provision[0]['name'],
            TaskHelper.make_slave_name(self.env.nodes[0].id,
                                       self.env.nodes[0].role)
        )

        # deploy method call [1][0][1][1]
        n_rpc_deploy = nailgun.task.manager.rpc.cast. \
            call_args_list[1][0][1][1]['args']['nodes']
        self.assertEquals(len(n_rpc_deploy), 1)
        self.assertEquals(n_rpc_deploy[0]['uid'], self.env.nodes[0].id)
Example #11
0
    def node_list(cls, nodes):
        """Generate nodes list. Represents
        as "nodes" parameter in facts.
        """
        node_list = []

        for node in nodes:
            for role in node.all_roles:
                node_list.append({
                    'uid': node.uid,
                    'fqdn': node.fqdn,
                    'name': TaskHelper.make_slave_name(node.id),
                    'role': role})

        return node_list
Example #12
0
    def node_list(cls, nodes):
        """Generate nodes list. Represents
        as "nodes" parameter in facts.
        """
        node_list = []

        for node in nodes:
            for role in node.all_roles:
                node_list.append({
                    'uid': node.uid,
                    'fqdn': node.fqdn,
                    'name': TaskHelper.make_slave_name(node.id),
                    'role': role})

        return node_list
Example #13
0
 def message(cls, task):
     nodes_to_reset = db().query(Node).filter(
         Node.cluster_id == task.cluster.id).yield_per(100)
     return make_astute_message(
         "reset_environment", "reset_environment_resp", {
             "task_uuid":
             task.uuid,
             "nodes": [{
                 'uid': n.uid,
                 'roles': n.roles,
                 'slave_name': TaskHelper.make_slave_name(n.id)
             } for n in nodes_to_reset],
             "engine": {
                 "url": settings.COBBLER_URL,
                 "username": settings.COBBLER_USER,
                 "password": settings.COBBLER_PASSWORD,
                 "master_ip": settings.MASTER_IP,
             }
         })
Example #14
0
 def message(cls, task):
     nodes_to_reset = db().query(Node).filter(
         Node.cluster_id == task.cluster.id
     ).yield_per(100)
     return {
         "method": "reset_environment",
         "respond_to": "reset_environment_resp",
         "args": {
             "task_uuid": task.uuid,
             "nodes": [
                 {
                     'uid': n.uid,
                     'roles': n.roles,
                     'slave_name': TaskHelper.make_slave_name(n.id)
                 } for n in nodes_to_reset
             ],
             "engine": {
                 "url": settings.COBBLER_URL,
                 "username": settings.COBBLER_USER,
                 "password": settings.COBBLER_PASSWORD,
             }
         }
     }
Example #15
0
 def message(cls, task, deploy_task):
     nodes_to_stop = db().query(Node).filter(
         Node.cluster_id == task.cluster.id).filter(
             not_(Node.status == 'ready')).yield_per(100)
     return {
         "method": "stop_deploy_task",
         "respond_to": "stop_deployment_resp",
         "args": {
             "task_uuid":
             task.uuid,
             "stop_task_uuid":
             deploy_task.uuid,
             "nodes": [{
                 'uid': n.uid,
                 'roles': n.roles,
                 'slave_name': TaskHelper.make_slave_name(n.id)
             } for n in nodes_to_stop],
             "engine": {
                 "url": settings.COBBLER_URL,
                 "username": settings.COBBLER_USER,
                 "password": settings.COBBLER_PASSWORD,
             }
         }
     }
    def test_neutron_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(
            cluster_kwargs={
                'mode': 'ha_compact',
                'net_provider': 'neutron',
                'net_segment_type': 'gre'
            },
            nodes_kwargs=[
                {'roles': ['controller'], 'pending_addition': True},
                {'roles': ['controller'], 'pending_addition': True},
                {'roles': ['controller', 'cinder'], 'pending_addition': True},
                {'roles': ['compute', 'cinder'], 'pending_addition': True},
                {'roles': ['compute'], 'pending_addition': True},
                {'roles': ['cinder'], 'pending_addition': True}
            ]
        )

        cluster_db = self.env.clusters[0]

        common_attrs = {
            'deployment_mode': 'ha_compact',

            'management_vip': '192.168.0.1',
            'public_vip': '172.16.0.2',

            'management_network_range': '192.168.0.0/24',
            'storage_network_range': '192.168.1.0/24',

            'mp': [{'weight': '1', 'point': '1'},
                   {'weight': '2', 'point': '2'}],

            'quantum': True,
            'quantum_settings': {},

            'master_ip': '127.0.0.1',
            'use_cinder': True,
            'deployment_id': cluster_db.id
        }

        cluster_attrs = cluster_db.attributes.merged_attrs_values()
        common_attrs.update(cluster_attrs)

        L2 = {
            "base_mac": "fa:16:3e:00:00:00",
            "segmentation_type": "gre",
            "phys_nets": {
                "physnet1": {
                    "bridge": "br-ex",
                    "vlan_range": None},
                "physnet2": {
                    "bridge": "br-prv",
                    "vlan_range": None}
            },
            "tunnel_id_ranges": "2:65535"
        }
        L3 = {
            "use_namespaces": True
        }
        predefined_networks = {
            "net04_ext": {
                'shared': False,
                'L2': {
                    'router_ext': True,
                    'network_type': 'flat',
                    'physnet': 'physnet1',
                    'segment_id': None},
                'L3': {
                    'subnet': u'172.16.0.0/24',
                    'enable_dhcp': False,
                    'nameservers': [],
                    'floating': '172.16.0.130:172.16.0.254',
                    'gateway': '172.16.0.1'},
                'tenant': 'admin'
            },
            "net04": {
                'shared': False,
                'L2': {
                    'router_ext': False,
                    'network_type': 'gre',
                    'physnet': 'physnet2',
                    'segment_id': None},
                'L3': {
                    'subnet': u'192.168.111.0/24',
                    'enable_dhcp': True,
                    'nameservers': [
                        '8.8.4.4',
                        '8.8.8.8'],
                    'floating': None,
                    'gateway': '192.168.111.1'},
                'tenant': 'admin'
            }
        }
        common_attrs['quantum_settings'].update(
            L2=L2,
            L3=L3,
            predefined_networks=predefined_networks)

        # Common attrs calculation
        nodes_list = []
        nodes_db = sorted(cluster_db.nodes, key=lambda n: n.id)
        assigned_ips = {}
        i = 0
        admin_ips = [
            '10.20.0.139/24',
            '10.20.0.138/24',
            '10.20.0.135/24',
            '10.20.0.133/24',
            '10.20.0.131/24',
            '10.20.0.130/24']
        for node in nodes_db:
            node_id = node.id
            admin_ip = admin_ips.pop()
            for role in sorted(node.roles + node.pending_roles):
                assigned_ips[node_id] = {}
                assigned_ips[node_id]['management'] = '192.168.0.%d' % (i + 2)
                assigned_ips[node_id]['public'] = '172.16.0.%d' % (i + 3)
                assigned_ips[node_id]['storage'] = '192.168.1.%d' % (i + 1)
                assigned_ips[node_id]['admin'] = admin_ip

                nodes_list.append({
                    'role': role,

                    'internal_address': assigned_ips[node_id]['management'],
                    'public_address': assigned_ips[node_id]['public'],
                    'storage_address': assigned_ips[node_id]['storage'],

                    'internal_netmask': '255.255.255.0',
                    'public_netmask': '255.255.255.0',
                    'storage_netmask': '255.255.255.0',

                    'uid': str(node_id),
                    'swift_zone': str(node_id),

                    'name': 'node-%d' % node_id,
                    'fqdn': 'node-%d.%s' % (node_id, settings.DNS_DOMAIN)})
            i += 1

        controller_nodes = filter(
            lambda node: node['role'] == 'controller',
            deepcopy(nodes_list))

        common_attrs['nodes'] = nodes_list
        common_attrs['nodes'][0]['role'] = 'primary-controller'

        common_attrs['last_controller'] = controller_nodes[-1]['name']

        # Individual attrs calculation and
        # merging with common attrs
        priority_mapping = {
            'controller': [600, 500, 400],
            'cinder': 700,
            'compute': 700
        }
        deployment_info = []
        for node in nodes_db:
            ips = assigned_ips[node.id]
            for role in sorted(node.roles):
                priority = priority_mapping[role]
                if isinstance(priority, list):
                    priority = priority.pop()

                individual_atts = {
                    'uid': str(node.id),
                    'status': node.status,
                    'role': role,
                    'online': node.online,
                    'fqdn': 'node-%d.%s' % (node.id, settings.DNS_DOMAIN),
                    'priority': priority,

                    'network_scheme': {
                        "version": "1.0",
                        "provider": "ovs",
                        "interfaces": {
                            "eth0": {
                                "L2": {"vlan_splinters": "off"},
                                "mtu": 1500
                            },
                            "eth1": {
                                "L2": {"vlan_splinters": "off"},
                                "mtu": 1500
                            },
                            "eth2": {
                                "L2": {"vlan_splinters": "off"},
                                "mtu": 1500
                            },
                        },
                        "endpoints": {
                            "br-mgmt": {"IP": [ips['management'] + "/24"]},
                            "br-ex": {
                                "IP": [ips['public'] + "/24"],
                                "gateway": "172.16.0.1"
                            },
                            "br-storage": {"IP": [ips['storage'] + "/24"]},
                            "eth1": {"IP": [ips['admin']]}
                        },
                        "roles": {
                            "management": "br-mgmt",
                            "mesh": "br-mgmt",
                            "ex": "br-ex",
                            "storage": "br-storage",
                            "fw-admin": "eth1"
                        },
                        "transformations": [
                            {
                                "action": "add-br",
                                "name": "br-ex"},
                            {
                                "action": "add-br",
                                "name": "br-mgmt"},
                            {
                                "action": "add-br",
                                "name": "br-storage"},
                            {
                                "action": "add-br",
                                "name": "br-prv"},
                            {
                                "action": "add-br",
                                "name": u"br-eth0"},
                            {
                                "action": "add-port",
                                "bridge": u"br-eth0",
                                "name": u"eth0"},
                            {
                                "action": "add-patch",
                                "bridges": [u"br-eth0", "br-storage"],
                                "tags": [102, 0]},
                            {
                                "action": "add-patch",
                                "bridges": [u"br-eth0", "br-ex"],
                                "trunks": [0]},
                            {
                                "action": "add-patch",
                                "bridges": [u"br-eth0", "br-mgmt"],
                                "tags": [101, 0]}
                        ]
                    }
                }

                individual_atts.update(common_attrs)
                individual_atts['glance']['image_cache_max_size'] = str(
                    manager.calc_glance_cache_size(node.attributes.volumes)
                )
                deployment_info.append(deepcopy(individual_atts))

        controller_nodes = filter(
            lambda node: node['role'] == 'controller',
            deployment_info)
        controller_nodes[0]['role'] = 'primary-controller'

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [x.uuid for x in supertask.subtasks
                            if x.name == 'deployment'][0]

        deployment_msg = {'method': 'deploy',
                          'respond_to': 'deploy_resp',
                          'args': {}}

        deployment_msg['args']['task_uuid'] = deploy_task_uuid
        deployment_msg['args']['deployment_info'] = deployment_info

        provision_nodes = []
        admin_net = self.env.network_manager.get_admin_network_group()

        for n in sorted(self.env.nodes, key=lambda n: n.id):
            udev_interfaces_mapping = ','.join([
                '{0}_{1}'.format(i.mac, i.name) for i in n.interfaces])
            eth1_mac = [i.mac for i in n.interfaces if i.name == 'eth1'][0]

            pnd = {
                'profile': cluster_attrs['cobbler']['profile'],
                'power_type': 'ssh',
                'power_user': '******',
                'kernel_options': {
                    'netcfg/choose_interface': eth1_mac,
                    'udevrules': udev_interfaces_mapping},
                'power_address': n.ip,
                'power_pass': settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                'name': TaskHelper.make_slave_name(n.id),
                'hostname': n.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'ks_spaces': n.attributes.volumes,
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                }
            }

            NetworkManager.assign_admin_ips(
                n.id,
                len(n.meta.get('interfaces', []))
            )

            admin_ips = set([i.ip_addr
                             for i in self.db.query(IPAddr).
                             filter_by(node=n.id).
                             filter_by(network=admin_net.id)])

            for i in n.meta.get('interfaces', []):
                if 'interfaces' not in pnd:
                    pnd['interfaces'] = {}
                pnd['interfaces'][i['name']] = {
                    'mac_address': i['mac'],
                    'static': '0',
                    'netmask': admin_net.netmask,
                    'ip_address': admin_ips.pop(),
                }
                if 'interfaces_extra' not in pnd:
                    pnd['interfaces_extra'] = {}
                pnd['interfaces_extra'][i['name']] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                if i['mac'] == n.mac:
                    pnd['interfaces'][i['name']]['dns_name'] = n.fqdn
                    pnd['interfaces_extra'][i['name']]['onboot'] = 'yes'

            provision_nodes.append(pnd)

        provision_task_uuid = filter(
            lambda t: t.name == 'provision',
            supertask.subtasks)[0].uuid

        provision_msg = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': provision_task_uuid,
                'provisioning_info': {
                    'engine': {
                        'url': settings.COBBLER_URL,
                        'username': settings.COBBLER_USER,
                        'password': settings.COBBLER_PASSWORD},
                    'nodes': provision_nodes}}}

        args, kwargs = nailgun.task.manager.rpc.cast.call_args
        self.assertEquals(len(args), 2)
        self.assertEquals(len(args[1]), 2)

        self.datadiff(args[1][0], provision_msg)
        self.datadiff(args[1][1], deployment_msg)
Example #17
0
    def execute(self, task, respond_to='remove_nodes_resp'):
        logger.debug("DeletionTask.execute(task=%s)" % task.uuid)
        task_uuid = task.uuid
        logger.debug("Nodes deletion task is running")
        nodes_to_delete = []
        nodes_to_delete_constant = []
        nodes_to_restore = []

        USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP

        # no need to call naily if there are no nodes in cluster
        if respond_to == 'remove_cluster_resp' and \
                not list(task.cluster.nodes):
            rcvr = rpc.receiver.NailgunReceiver()
            rcvr.remove_cluster_resp(
                task_uuid=task_uuid,
                status='ready',
                progress=100
            )
            return

        for node in task.cluster.nodes:
            if node.pending_deletion:
                nodes_to_delete.append({
                    'id': node.id,
                    'uid': node.id,
                    'roles': node.roles
                })

                if USE_FAKE:
                    # only fake tasks
                    new_node = {}
                    keep_attrs = (
                        'id',
                        'cluster_id',
                        'roles',
                        'pending_deletion',
                        'pending_addition'
                    )
                    for prop in object_mapper(node).iterate_properties:
                        if isinstance(
                            prop, ColumnProperty
                        ) and prop.key not in keep_attrs:
                            new_node[prop.key] = getattr(node, prop.key)
                    nodes_to_restore.append(new_node)
                    # /only fake tasks

        # this variable is used to iterate over it
        # and be able to delete node from nodes_to_delete safely
        nodes_to_delete_constant = list(nodes_to_delete)

        for node in nodes_to_delete_constant:
            node_db = db().query(Node).get(node['id'])

            slave_name = TaskHelper.make_slave_name(node['id'])
            logger.debug("Removing node from database and pending it "
                         "to clean its MBR: %s", slave_name)
            if not node_db.online:
                logger.info(
                    "Node is offline, can't MBR clean: %s", slave_name)
                db().delete(node_db)
                db().commit()

                nodes_to_delete.remove(node)

        # only real tasks
        engine_nodes = []
        if not USE_FAKE:
            for node in nodes_to_delete_constant:
                slave_name = TaskHelper.make_slave_name(node['id'])
                logger.debug("Pending node to be removed from cobbler %s",
                             slave_name)
                engine_nodes.append(slave_name)
                try:
                    node_db = db().query(Node).get(node['id'])
                    if node_db and node_db.fqdn:
                        node_hostname = node_db.fqdn
                    else:
                        node_hostname = TaskHelper.make_slave_fqdn(node['id'])
                    logger.info("Removing node cert from puppet: %s",
                                node_hostname)
                    cmd = "puppet cert clean {0}".format(node_hostname)
                    proc = subprocess.Popen(
                        shlex.split(cmd),
                        shell=False,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE
                    )
                    p_stdout, p_stderr = proc.communicate()
                    logger.info(
                        "'{0}' executed, STDOUT: '{1}',"
                        " STDERR: '{2}'".format(
                            cmd,
                            p_stdout,
                            p_stderr
                        )
                    )
                except OSError:
                    logger.warning(
                        "'{0}' returned non-zero exit code".format(
                            cmd
                        )
                    )
                except Exception as e:
                    logger.warning("Exception occurred while trying to \
                            remove the system from Cobbler: '{0}'".format(
                        e.message))

        msg_delete = {
            'method': 'remove_nodes',
            'respond_to': respond_to,
            'args': {
                'task_uuid': task.uuid,
                'nodes': nodes_to_delete,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                },
                'engine_nodes': engine_nodes
            }
        }
        # only fake tasks
        if USE_FAKE and nodes_to_restore:
            msg_delete['args']['nodes_to_restore'] = nodes_to_restore
        # /only fake tasks
        logger.debug("Calling rpc remove_nodes method")
        rpc.cast('naily', msg_delete)
Example #18
0
    def execute(self, task, respond_to='remove_nodes_resp'):
        logger.debug("DeletionTask.execute(task=%s)" % task.uuid)
        task_uuid = task.uuid
        logger.debug("Nodes deletion task is running")
        nodes_to_delete = []
        nodes_to_delete_constant = []
        nodes_to_restore = []

        USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP

        # no need to call naily if there are no nodes in cluster
        if respond_to == 'remove_cluster_resp' and \
                not list(task.cluster.nodes):
            rcvr = rpc.receiver.NailgunReceiver()
            rcvr.remove_cluster_resp(
                task_uuid=task_uuid,
                status='ready',
                progress=100
            )
            return

        for node in task.cluster.nodes:
            if node.pending_deletion:
                nodes_to_delete.append({
                    'id': node.id,
                    'uid': node.id,
                    'roles': node.roles,
                    'slave_name': TaskHelper.make_slave_name(node.id)
                })

                if USE_FAKE:
                    # only fake tasks
                    new_node = {}
                    keep_attrs = (
                        'id',
                        'cluster_id',
                        'roles',
                        'pending_deletion',
                        'pending_addition'
                    )
                    for prop in object_mapper(node).iterate_properties:
                        if isinstance(
                            prop, ColumnProperty
                        ) and prop.key not in keep_attrs:
                            new_node[prop.key] = getattr(node, prop.key)
                    nodes_to_restore.append(new_node)
                    # /only fake tasks

        # this variable is used to iterate over it
        # and be able to delete node from nodes_to_delete safely
        nodes_to_delete_constant = list(nodes_to_delete)

        for node in nodes_to_delete_constant:
            node_db = db().query(Node).get(node['id'])

            slave_name = TaskHelper.make_slave_name(node['id'])
            logger.debug("Removing node from database and pending it "
                         "to clean its MBR: %s", slave_name)
            if node_db.status == 'discover':
                logger.info(
                    "Node is not deployed yet,"
                    " can't clean MBR: %s", slave_name)
                db().delete(node_db)
                db().commit()

                nodes_to_delete.remove(node)

        msg_delete = {
            'method': 'remove_nodes',
            'respond_to': respond_to,
            'args': {
                'task_uuid': task.uuid,
                'nodes': nodes_to_delete,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                }
            }
        }
        # only fake tasks
        if USE_FAKE and nodes_to_restore:
            msg_delete['args']['nodes_to_restore'] = nodes_to_restore
        # /only fake tasks
        logger.debug("Calling rpc remove_nodes method")
        rpc.cast('naily', msg_delete)
Example #19
0
    def message(cls, task):
        logger.debug("ProvisionTask.message(task=%s)" % task.uuid)
        task_uuid = task.uuid
        cluster_id = task.cluster.id
        cluster_attrs = task.cluster.attributes.merged_attrs_values()

        netmanager = NetworkManager()
        nodes = orm().query(Node).filter_by(
            cluster_id=task.cluster.id,
            pending_deletion=False).order_by(Node.id)

        USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP

        nodes_to_provision = []

        # FIXME: why can't we use needs_reprovision and pending_addition
        # attributes of node to constract valid list of nodes which need
        # to be provisioned and instead use this ugly loop?
        for node in nodes:
            if not node.online:
                if not USE_FAKE:
                    raise Exception(
                        u"Node '%s' (id=%s) is offline."
                        " Remove it from environment and try again." %
                        (node.name, node.id)
                    )
                else:
                    logger.warning(
                        u"Node '%s' (id=%s) is offline."
                        " Remove it from environment and try again." %
                        (node.name, node.id)
                    )
            if node.status in ('discover', 'provisioning') or \
                    (node.status == 'error' and
                     node.error_type == 'provision'):
                nodes_to_provision.append(node)

        # TODO: For now we send nodes data to orchestrator
        # which are cobbler oriented. But for future we
        # need to use more abstract data structure.
        nodes_data = []
        for node in nodes_to_provision:
            node_data = {
                'profile': settings.COBBLER_PROFILE,
                'power_type': 'ssh',
                'power_user': '******',
                'power_address': node.ip,
                'name': TaskHelper.make_slave_name(node.id, node.role),
                'hostname': node.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                    'ks_spaces': "\"%s\"" % json.dumps(
                        node.attributes.volumes).replace("\"", "\\\"")
                }
            }

            if node.status == "discover":
                logger.info(
                    "Node %s seems booted with bootstrap image",
                    node.id
                )
                node_data['power_pass'] = settings.PATH_TO_BOOTSTRAP_SSH_KEY
            else:
                # If it's not in discover, we expect it to be booted
                #   in target system.
                # TODO: Get rid of expectations!
                logger.info(
                    "Node %s seems booted with real system",
                    node.id
                )
                node_data['power_pass'] = settings.PATH_TO_SSH_KEY

            # FIXME: move this code (updating) into receiver.provision_resp
            if not USE_FAKE:
                node.status = "provisioning"
                orm().add(node)
                orm().commit()

            # here we assign admin network IPs for node
            # one IP for every node interface
            netmanager.assign_admin_ips(
                node.id,
                len(node.meta.get('interfaces', []))
            )
            admin_net_id = netmanager.get_admin_network_id()
            admin_ips = set([i.ip_addr for i in orm().query(IPAddr).
                            filter_by(node=node.id).
                            filter_by(network=admin_net_id)])
            for i in node.meta.get('interfaces', []):
                if 'interfaces' not in node_data:
                    node_data['interfaces'] = {}
                node_data['interfaces'][i['name']] = {
                    'mac_address': i['mac'],
                    'static': '0',
                    'netmask': settings.ADMIN_NETWORK['netmask'],
                    'ip_address': admin_ips.pop(),
                }
                # interfaces_extra field in cobbler ks_meta
                # means some extra data for network interfaces
                # configuration. It is used by cobbler snippet.
                # For example, cobbler interface model does not
                # have 'peerdns' field, but we need this field
                # to be configured. So we use interfaces_extra
                # branch in order to set this unsupported field.
                if 'interfaces_extra' not in node_data:
                    node_data['interfaces_extra'] = {}
                node_data['interfaces_extra'][i['name']] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                # We want node to be able to PXE boot via any of its
                # interfaces. That is why we add all discovered
                # interfaces into cobbler system. But we want
                # assignted fqdn to be resolved into one IP address
                # because we don't completely support multiinterface
                # configuration yet.
                if i['mac'] == node.mac:
                    node_data['interfaces'][i['name']]['dns_name'] = node.fqdn
                    node_data['interfaces_extra'][i['name']]['onboot'] = 'yes'

            nodes_data.append(node_data)
            if not USE_FAKE:
                TaskHelper.prepare_syslog_dir(node)

        message = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': task.uuid,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                },
                'nodes': nodes_data
            }
        }
        return message
Example #20
0
    def execute(self, task, respond_to='remove_nodes_resp'):
        logger.debug("DeletionTask.execute(task=%s)" % task.uuid)
        task_uuid = task.uuid
        logger.debug("Nodes deletion task is running")
        nodes_to_delete = []
        nodes_to_delete_constant = []
        nodes_to_restore = []

        USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP

        # no need to call naily if there are no nodes in cluster
        if respond_to == 'remove_cluster_resp' and \
                not list(task.cluster.nodes):
            rcvr = rpc.receiver.NailgunReceiver()
            rcvr.remove_cluster_resp(task_uuid=task_uuid,
                                     status='ready',
                                     progress=100)
            return

        for node in task.cluster.nodes:
            if node.pending_deletion:
                nodes_to_delete.append({
                    'id': node.id,
                    'uid': node.id,
                    'roles': node.roles
                })

                if USE_FAKE:
                    # only fake tasks
                    new_node = {}
                    keep_attrs = ('id', 'cluster_id', 'roles',
                                  'pending_deletion', 'pending_addition')
                    for prop in object_mapper(node).iterate_properties:
                        if isinstance(
                                prop,
                                ColumnProperty) and prop.key not in keep_attrs:
                            new_node[prop.key] = getattr(node, prop.key)
                    nodes_to_restore.append(new_node)
                    # /only fake tasks

        # this variable is used to iterate over it
        # and be able to delete node from nodes_to_delete safely
        nodes_to_delete_constant = list(nodes_to_delete)

        for node in nodes_to_delete_constant:
            node_db = db().query(Node).get(node['id'])

            slave_name = TaskHelper.make_slave_name(node['id'])
            logger.debug(
                "Removing node from database and pending it "
                "to clean its MBR: %s", slave_name)
            if not node_db.online or node_db.status == 'discover':
                logger.info(
                    "Node is offline or not deployed yet,"
                    " can't clean MBR: %s", slave_name)
                db().delete(node_db)
                db().commit()

                nodes_to_delete.remove(node)

        # only real tasks
        engine_nodes = []
        if not USE_FAKE:
            for node in nodes_to_delete_constant:
                slave_name = TaskHelper.make_slave_name(node['id'])
                logger.debug("Pending node to be removed from cobbler %s",
                             slave_name)
                engine_nodes.append(slave_name)
                try:
                    node_db = db().query(Node).get(node['id'])
                    if node_db and node_db.fqdn:
                        node_hostname = node_db.fqdn
                    else:
                        node_hostname = TaskHelper.make_slave_fqdn(node['id'])
                    logger.info("Removing node cert from puppet: %s",
                                node_hostname)
                    cmd = "puppet cert clean {0}".format(node_hostname)
                    proc = subprocess.Popen(shlex.split(cmd),
                                            shell=False,
                                            stdout=subprocess.PIPE,
                                            stderr=subprocess.PIPE)
                    p_stdout, p_stderr = proc.communicate()
                    logger.info("'{0}' executed, STDOUT: '{1}',"
                                " STDERR: '{2}'".format(
                                    cmd, p_stdout, p_stderr))
                except OSError:
                    logger.warning(
                        "'{0}' returned non-zero exit code".format(cmd))
                except Exception as e:
                    logger.warning("Exception occurred while trying to \
                            remove the system from Cobbler: '{0}'".format(
                        e.message))

        msg_delete = {
            'method': 'remove_nodes',
            'respond_to': respond_to,
            'args': {
                'task_uuid': task.uuid,
                'nodes': nodes_to_delete,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                },
                'engine_nodes': engine_nodes
            }
        }
        # only fake tasks
        if USE_FAKE and nodes_to_restore:
            msg_delete['args']['nodes_to_restore'] = nodes_to_restore
        # /only fake tasks
        logger.debug("Calling rpc remove_nodes method")
        rpc.cast('naily', msg_delete)
Example #21
0
    def message(cls, task):
        logger.debug("ProvisionTask.message(task=%s)" % task.uuid)
        # this variable is used to set 'auth_key' in cobbler ks_meta
        cluster_attrs = task.cluster.attributes.merged_attrs_values()
        nodes = TaskHelper.nodes_to_provision(task.cluster)
        netmanager = NetworkManager()

        USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP
        # TODO: For now we send nodes data to orchestrator
        # which is cobbler oriented. But for future we
        # need to use more abstract data structure.
        nodes_data = []
        for node in nodes:
            if not node.online:
                if not USE_FAKE:
                    raise Exception(
                        u"Node '%s' (id=%s) is offline."
                        " Remove it from environment and try again." %
                        (node.name, node.id)
                    )
                else:
                    logger.warning(
                        u"Node '%s' (id=%s) is offline."
                        " Remove it from environment and try again." %
                        (node.name, node.id)
                    )

            node_data = {
                'profile': settings.COBBLER_PROFILE,
                'power_type': 'ssh',
                'power_user': '******',
                'power_address': node.ip,
                'name': TaskHelper.make_slave_name(node.id, node.role),
                'hostname': node.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                    'ks_spaces': "\"%s\"" % json.dumps(
                        node.attributes.volumes).replace("\"", "\\\"")
                }
            }

            if node.status == "discover":
                logger.info(
                    "Node %s seems booted with bootstrap image",
                    node.id
                )
                node_data['power_pass'] = settings.PATH_TO_BOOTSTRAP_SSH_KEY
            else:
                # If it's not in discover, we expect it to be booted
                #   in target system.
                # TODO: Get rid of expectations!
                logger.info(
                    "Node %s seems booted with real system",
                    node.id
                )
                node_data['power_pass'] = settings.PATH_TO_SSH_KEY

            # FIXME: move this code (updating) into receiver.provision_resp
            if not USE_FAKE:
                node.status = "provisioning"
                orm().add(node)
                orm().commit()

            # here we assign admin network IPs for node
            # one IP for every node interface
            netmanager.assign_admin_ips(
                node.id,
                len(node.meta.get('interfaces', []))
            )
            admin_net_id = netmanager.get_admin_network_id()
            admin_ips = set([i.ip_addr for i in orm().query(IPAddr).
                            filter_by(node=node.id).
                            filter_by(network=admin_net_id)])
            for i in node.meta.get('interfaces', []):
                if 'interfaces' not in node_data:
                    node_data['interfaces'] = {}
                node_data['interfaces'][i['name']] = {
                    'mac_address': i['mac'],
                    'static': '0',
                    'netmask': settings.ADMIN_NETWORK['netmask'],
                    'ip_address': admin_ips.pop(),
                }
                # interfaces_extra field in cobbler ks_meta
                # means some extra data for network interfaces
                # configuration. It is used by cobbler snippet.
                # For example, cobbler interface model does not
                # have 'peerdns' field, but we need this field
                # to be configured. So we use interfaces_extra
                # branch in order to set this unsupported field.
                if 'interfaces_extra' not in node_data:
                    node_data['interfaces_extra'] = {}
                node_data['interfaces_extra'][i['name']] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                # We want node to be able to PXE boot via any of its
                # interfaces. That is why we add all discovered
                # interfaces into cobbler system. But we want
                # assignted fqdn to be resolved into one IP address
                # because we don't completely support multiinterface
                # configuration yet.
                if i['mac'] == node.mac:
                    node_data['interfaces'][i['name']]['dns_name'] = node.fqdn
                    node_data['interfaces_extra'][i['name']]['onboot'] = 'yes'

            nodes_data.append(node_data)
            if not USE_FAKE:
                TaskHelper.prepare_syslog_dir(node)

        message = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': task.uuid,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                },
                'nodes': nodes_data
            }
        }
        return message
Example #22
0
    def execute(self, task, respond_to='remove_nodes_resp'):
        logger.debug("DeletionTask.execute(task=%s)" % task.uuid)
        task_uuid = task.uuid
        logger.debug("Nodes deletion task is running")
        nodes_to_delete = []
        nodes_to_restore = []

        USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP

        # no need to call naily if there are no nodes in cluster
        if respond_to == 'remove_cluster_resp' and \
                not list(task.cluster.nodes):
            rcvr = rpc.receiver.NailgunReceiver()
            rcvr.initialize()
            rcvr.remove_cluster_resp(
                task_uuid=task_uuid,
                status='ready',
                progress=100
            )
            return

        for node in task.cluster.nodes:
            if node.pending_deletion:
                nodes_to_delete.append({
                    'id': node.id,
                    'uid': node.id,
                    'role': node.role
                })

                if USE_FAKE:
                    # only fake tasks
                    new_node = Node()
                    keep_attrs = (
                        'id',
                        'cluster_id',
                        'role',
                        'pending_deletion',
                        'pending_addition'
                    )
                    for prop in object_mapper(new_node).iterate_properties:
                        if isinstance(
                            prop, ColumnProperty
                        ) and prop.key not in keep_attrs:
                            setattr(
                                new_node,
                                prop.key,
                                getattr(node, prop.key)
                            )
                    nodes_to_restore.append(new_node)
                    # /only fake tasks

        # Deletion offline nodes from db
        if nodes_to_delete:
            for node in list(nodes_to_delete):
                node_db = orm().query(Node).get(node['id'])

                if not node_db.online:
                    slave_name = TaskHelper.make_slave_name(
                        node['id'], node['role']
                    )
                    logger.info(
                        "Node %s is offline, removing node from db" %
                        slave_name)
                    orm().delete(node_db)
                    orm().commit()

                    nodes_to_delete.remove(node)

        # only real tasks
        engine_nodes = []
        if not USE_FAKE:
            if nodes_to_delete:
                logger.debug("There are nodes to delete")
                for node in nodes_to_delete:
                    slave_name = TaskHelper.make_slave_name(
                        node['id'], node['role']
                    )
                    engine_nodes.append(slave_name)
                    try:
                        logger.info("Deleting old certs from puppet..")
                        node_db = orm().query(Node).get(node['id'])
                        if node_db and node_db.fqdn:
                            node_hostname = node_db.fqdn
                        else:
                            node_hostname = '.'.join([
                                slave_name, settings.DNS_DOMAIN])
                        cmd = "puppet cert clean {0}".format(node_hostname)
                        proc = subprocess.Popen(
                            shlex.split(cmd),
                            shell=False,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE
                        )
                        p_stdout, p_stderr = proc.communicate()
                        logger.info(
                            "'{0}' executed, STDOUT: '{1}',"
                            " STDERR: '{2}'".format(
                                cmd,
                                p_stdout,
                                p_stderr
                            )
                        )
                    except OSError:
                        logger.warning(
                            "'{0}' returned non-zero exit code".format(
                                cmd
                            )
                        )
                    except Exception as e:
                        logger.warning("Exception occurred while trying to \
                                remove the system from Cobbler: '{0}'".format(
                            e.message))

        # /only real tasks

        msg_delete = {
            'method': 'remove_nodes',
            'respond_to': respond_to,
            'args': {
                'task_uuid': task.uuid,
                'nodes': nodes_to_delete,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                },
                'engine_nodes': engine_nodes
            }
        }
        # only fake tasks
        if USE_FAKE and nodes_to_restore:
            msg_delete['args']['nodes_to_restore'] = nodes_to_restore
        # /only fake tasks
        logger.debug("Calling rpc remove_nodes method")
        rpc.cast('naily', msg_delete)
    def test_nova_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(cluster_kwargs={'mode': 'ha_compact'},
                        nodes_kwargs=[{
                            'roles': ['controller'],
                            'pending_addition': True
                        }, {
                            'roles': ['controller'],
                            'pending_addition': True
                        }, {
                            'roles': ['controller', 'cinder'],
                            'pending_addition': True
                        }, {
                            'roles': ['compute', 'cinder'],
                            'pending_addition': True
                        }, {
                            'roles': ['compute'],
                            'pending_addition': True
                        }, {
                            'roles': ['cinder'],
                            'pending_addition': True
                        }])

        cluster_db = self.env.clusters[0]

        common_attrs = {
            'deployment_mode': 'ha_compact',
            'management_vip': '192.168.0.2',
            'public_vip': '172.16.0.2',
            'fixed_network_range': '10.0.0.0/16',
            'management_network_range': '192.168.0.0/24',
            'floating_network_range': ['172.16.0.128-172.16.0.254'],
            'storage_network_range': '192.168.1.0/24',
            'mp': [{
                'weight': '1',
                'point': '1'
            }, {
                'weight': '2',
                'point': '2'
            }],
            'novanetwork_parameters': {
                'network_manager': 'FlatDHCPManager',
                'network_size': 256
            },
            'dns_nameservers': ["8.8.8.8", "8.8.4.4"],
            'management_interface': 'eth0.101',
            'fixed_interface': 'eth0.103',
            'admin_interface': 'eth1',
            'storage_interface': 'eth0.102',
            'public_interface': 'eth0',
            'floating_interface': 'eth0',
            'master_ip': '127.0.0.1',
            'use_cinder': True,
            'deployment_id': cluster_db.id
        }

        cluster_attrs = cluster_db.attributes.merged_attrs_values()
        common_attrs.update(cluster_attrs)

        # Common attrs calculation
        nodes_list = []
        nodes_db = sorted(cluster_db.nodes, key=lambda n: n.id)
        assigned_ips = {}
        i = 0
        admin_ips = [
            '10.20.0.139/24', '10.20.0.138/24', '10.20.0.135/24',
            '10.20.0.133/24', '10.20.0.131/24', '10.20.0.130/24'
        ]
        for node in nodes_db:
            node_id = node.id
            admin_ip = admin_ips.pop()
            for role in sorted(node.roles + node.pending_roles):
                assigned_ips[node_id] = {}
                assigned_ips[node_id]['internal'] = '192.168.0.%d' % (i + 3)
                assigned_ips[node_id]['public'] = '172.16.0.%d' % (i + 3)
                assigned_ips[node_id]['storage'] = '192.168.1.%d' % (i + 2)
                assigned_ips[node_id]['admin'] = admin_ip

                nodes_list.append({
                    'role':
                    role,
                    'internal_address':
                    assigned_ips[node_id]['internal'],
                    'public_address':
                    assigned_ips[node_id]['public'],
                    'storage_address':
                    assigned_ips[node_id]['storage'],
                    'internal_netmask':
                    '255.255.255.0',
                    'public_netmask':
                    '255.255.255.0',
                    'storage_netmask':
                    '255.255.255.0',
                    'uid':
                    str(node_id),
                    'swift_zone':
                    str(node_id),
                    'name':
                    'node-%d' % node_id,
                    'fqdn':
                    'node-%d.%s' % (node_id, settings.DNS_DOMAIN)
                })
            i += 1

        controller_nodes = filter(lambda node: node['role'] == 'controller',
                                  deepcopy(nodes_list))

        common_attrs['nodes'] = nodes_list
        common_attrs['nodes'][0]['role'] = 'primary-controller'

        common_attrs['last_controller'] = controller_nodes[-1]['name']

        # Individual attrs calculation and
        # merging with common attrs
        priority_mapping = {
            'controller': [600, 500, 400],
            'cinder': 700,
            'compute': 700
        }

        deployment_info = []
        for node in nodes_db:
            ips = assigned_ips[node.id]
            for role in sorted(node.roles):
                priority = priority_mapping[role]
                if isinstance(priority, list):
                    priority = priority.pop()

                individual_atts = {
                    'uid': str(node.id),
                    'status': node.status,
                    'role': role,
                    'online': node.online,
                    'fqdn': 'node-%d.%s' % (node.id, settings.DNS_DOMAIN),
                    'priority': priority,
                    'network_data': {
                        'eth0': {
                            'interface': 'eth0',
                            'ipaddr': ['%s/24' % ips['public']],
                            'gateway': '172.16.0.1'
                        },
                        'eth0.101': {
                            'interface': 'eth0.101',
                            'ipaddr': ['%s/24' % ips['internal']]
                        },
                        'eth0.102': {
                            'interface': 'eth0.102',
                            'ipaddr': ['%s/24' % ips['storage']]
                        },
                        'eth0.103': {
                            'interface': 'eth0.103',
                            'ipaddr': 'none'
                        },
                        'lo': {
                            'interface': 'lo',
                            'ipaddr': ['127.0.0.1/8']
                        },
                        'eth1': {
                            'interface': 'eth1',
                            'ipaddr': [ips['admin']]
                        }
                    }
                }

                individual_atts.update(common_attrs)
                individual_atts['glance']['image_cache_max_size'] = str(
                    manager.calc_glance_cache_size(node.attributes.volumes))
                deployment_info.append(deepcopy(individual_atts))

        controller_nodes = filter(lambda node: node['role'] == 'controller',
                                  deployment_info)
        controller_nodes[0]['role'] = 'primary-controller'

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [
            x.uuid for x in supertask.subtasks if x.name == 'deployment'
        ][0]

        deployment_msg = {
            'method': 'deploy',
            'respond_to': 'deploy_resp',
            'args': {}
        }

        deployment_msg['args']['task_uuid'] = deploy_task_uuid
        deployment_msg['args']['deployment_info'] = deployment_info

        provision_nodes = []
        admin_net = self.env.network_manager.get_admin_network_group()

        for n in sorted(self.env.nodes, key=lambda n: n.id):
            udev_interfaces_mapping = ','.join(
                ['{0}_{1}'.format(i.mac, i.name) for i in n.interfaces])

            pnd = {
                'profile': cluster_attrs['cobbler']['profile'],
                'power_type': 'ssh',
                'power_user': '******',
                'kernel_options': {
                    'netcfg/choose_interface': 'eth1',
                    'udevrules': udev_interfaces_mapping
                },
                'power_address': n.ip,
                'power_pass': settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                'name': TaskHelper.make_slave_name(n.id),
                'hostname': n.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'ks_spaces': n.attributes.volumes,
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                }
            }

            NetworkManager.assign_admin_ips(n.id,
                                            len(n.meta.get('interfaces', [])))

            admin_ips = set([
                i.ip_addr for i in self.db.query(IPAddr).filter_by(
                    node=n.id).filter_by(network=admin_net.id)
            ])

            for i in n.interfaces:
                if 'interfaces' not in pnd:
                    pnd['interfaces'] = {}
                pnd['interfaces'][i.name] = {
                    'mac_address': i.mac,
                    'static': '0',
                    'netmask': admin_net.netmask,
                    'ip_address': admin_ips.pop(),
                }
                if 'interfaces_extra' not in pnd:
                    pnd['interfaces_extra'] = {}
                pnd['interfaces_extra'][i.name] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                if i.mac == n.mac:
                    pnd['interfaces'][i.name]['dns_name'] = n.fqdn
                    pnd['interfaces_extra'][i.name]['onboot'] = 'yes'

            provision_nodes.append(pnd)

        provision_task_uuid = filter(lambda t: t.name == 'provision',
                                     supertask.subtasks)[0].uuid

        provision_msg = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': provision_task_uuid,
                'provisioning_info': {
                    'engine': {
                        'url': settings.COBBLER_URL,
                        'username': settings.COBBLER_USER,
                        'password': settings.COBBLER_PASSWORD
                    },
                    'nodes': provision_nodes
                }
            }
        }

        args, kwargs = nailgun.task.manager.rpc.cast.call_args
        self.assertEquals(len(args), 2)
        self.assertEquals(len(args[1]), 2)

        self.datadiff(args[1][0], provision_msg)
        self.datadiff(args[1][1], deployment_msg)
    def test_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(
            cluster_kwargs={
                "mode": "ha",
                "type": "compute"
            },
            nodes_kwargs=[
                {"role": "controller", "pending_addition": True},
                {"role": "controller", "pending_addition": True},
                {"role": "controller", "pending_addition": True},
            ]
        )
        cluster_db = self.env.clusters[0]
        cluster_depl_mode = 'ha'

        # Set ip ranges for floating ips
        ranges = [['172.16.0.2', '172.16.0.4'],
                  ['172.16.0.3', '172.16.0.5'],
                  ['172.16.0.10', '172.16.0.12']]

        floating_network_group = self.db.query(NetworkGroup).filter(
            NetworkGroup.name == 'floating').filter(
                NetworkGroup.cluster_id == cluster_db.id).first()

        # Remove floating ip addr ranges
        self.db.query(IPAddrRange).filter(
            IPAddrRange.network_group_id == floating_network_group.id).delete()

        # Add new ranges
        for ip_range in ranges:
            new_ip_range = IPAddrRange(
                first=ip_range[0],
                last=ip_range[1],
                network_group_id=floating_network_group.id)

            self.db.add(new_ip_range)
        self.db.commit()

        # Update netmask for public network
        public_network_group = self.db.query(NetworkGroup).filter(
            NetworkGroup.name == 'public').filter(
                NetworkGroup.cluster_id == cluster_db.id).first()
        public_network_group.netmask = '255.255.255.128'
        self.db.commit()

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [x.uuid for x in supertask.subtasks
                            if x.name == 'deployment'][0]

        msg = {'method': 'deploy', 'respond_to': 'deploy_resp',
               'args': {}}
        self.db.add(cluster_db)
        cluster_attrs = cluster_db.attributes.merged_attrs_values()

        nets_db = self.db.query(Network).join(NetworkGroup).\
            filter(NetworkGroup.cluster_id == cluster_db.id).all()

        for net in nets_db:
            if net.name != 'public':
                cluster_attrs[net.name + '_network_range'] = net.cidr

        cluster_attrs['floating_network_range'] = [
            '172.16.0.2-172.16.0.4',
            '172.16.0.3-172.16.0.5',
            '172.16.0.10-172.16.0.12'
        ]

        management_vip = self.env.network_manager.assign_vip(
            cluster_db.id,
            'management'
        )
        public_vip = self.env.network_manager.assign_vip(
            cluster_db.id,
            'public'
        )

        net_params = {}
        net_params['network_manager'] = "FlatDHCPManager"
        net_params['network_size'] = 256

        cluster_attrs['novanetwork_parameters'] = net_params

        cluster_attrs['management_vip'] = management_vip
        cluster_attrs['public_vip'] = public_vip
        cluster_attrs['master_ip'] = '127.0.0.1'
        cluster_attrs['deployment_mode'] = cluster_depl_mode
        cluster_attrs['deployment_id'] = cluster_db.id

        msg['args']['attributes'] = cluster_attrs
        msg['args']['task_uuid'] = deploy_task_uuid
        nodes = []
        provision_nodes = []

        admin_net_id = self.env.network_manager.get_admin_network_id()

        for n in sorted(self.env.nodes, key=lambda n: n.id):

            q = self.db.query(IPAddr).join(Network).\
                filter(IPAddr.node == n.id).filter(
                    not_(IPAddr.network == admin_net_id)
                )

            """
            Here we want to get node IP addresses which belong
            to storage and management networks respectively
            """
            node_ip_management, node_ip_storage = map(
                lambda x: q.filter_by(name=x).first().ip_addr
                + "/" + cluster_attrs[x + '_network_range'].split('/')[1],
                ('management', 'storage')
            )
            node_ip_public = q.filter_by(name='public').first().ip_addr + '/25'

            nodes.append({'uid': n.id, 'status': n.status, 'ip': n.ip,
                          'error_type': n.error_type, 'mac': n.mac,
                          'role': n.role, 'id': n.id, 'fqdn':
                          '%s-%d.%s' % (n.role, n.id, settings.DNS_DOMAIN),
                          'progress': 0, 'meta': n.meta, 'online': True,
                          'network_data': [{'brd': '192.168.0.255',
                                            'ip': node_ip_management,
                                            'vlan': 101,
                                            'gateway': '192.168.0.1',
                                            'netmask': '255.255.255.0',
                                            'dev': 'eth0',
                                            'name': 'management'},
                                           {'brd': '172.16.1.255',
                                            'ip': node_ip_public,
                                            'vlan': 100,
                                            'gateway': '172.16.1.1',
                                            'netmask': '255.255.255.128',
                                            'dev': 'eth0',
                                            'name': u'public'},
                                           {'name': u'storage',
                                            'ip': node_ip_storage,
                                            'vlan': 102,
                                            'dev': 'eth0',
                                            'netmask': '255.255.255.0',
                                            'brd': '192.168.1.255',
                                            'gateway': u'192.168.1.1'},
                                           {'vlan': 100,
                                            'name': 'floating',
                                            'dev': 'eth0'},
                                           {'vlan': 103,
                                            'name': 'fixed',
                                            'dev': 'eth0'},
                                           {'name': u'admin',
                                            'dev': 'eth0'}]})

            pnd = {
                'profile': cluster_attrs['cobbler']['profile'],
                'power_type': 'ssh',
                'power_user': '******',
                'power_address': n.ip,
                'power_pass': settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                'name': TaskHelper.make_slave_name(n.id, n.role),
                'hostname': n.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'ks_spaces': "\"%s\"" % json.dumps(
                        n.attributes.volumes).replace("\"", "\\\""),
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                }
            }

            netmanager = NetworkManager()
            netmanager.assign_admin_ips(
                n.id,
                len(n.meta.get('interfaces', []))
            )

            admin_ips = set([i.ip_addr for i in self.db.query(IPAddr).
                            filter_by(node=n.id).
                            filter_by(network=admin_net_id)])

            for i in n.meta.get('interfaces', []):
                if 'interfaces' not in pnd:
                    pnd['interfaces'] = {}
                pnd['interfaces'][i['name']] = {
                    'mac_address': i['mac'],
                    'static': '0',
                    'netmask': settings.ADMIN_NETWORK['netmask'],
                    'ip_address': admin_ips.pop(),
                }
                if 'interfaces_extra' not in pnd:
                    pnd['interfaces_extra'] = {}
                pnd['interfaces_extra'][i['name']] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                if i['mac'] == n.mac:
                    pnd['interfaces'][i['name']]['dns_name'] = n.fqdn
                    pnd['interfaces_extra'][i['name']]['onboot'] = 'yes'

            provision_nodes.append(pnd)

        controller_nodes = filter(
            lambda node: node['role'] == 'controller',
            nodes)
        msg['args']['attributes']['controller_nodes'] = controller_nodes
        msg['args']['nodes'] = nodes

        provision_task_uuid = [x.uuid for x in supertask.subtasks
                               if x.name == 'provision'][0]
        provision_msg = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': provision_task_uuid,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                },
                'nodes': provision_nodes,
            }
        }

        args, kwargs = nailgun.task.manager.rpc.cast.call_args
        self.assertEquals(len(args), 2)
        self.assertEquals(len(args[1]), 2)

        self.datadiff(args[1][0], provision_msg)
        self.datadiff(args[1][1], msg)
    def test_nova_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(
            cluster_kwargs={"mode": "ha_compact"},
            nodes_kwargs=[
                {"roles": ["controller"], "pending_addition": True},
                {"roles": ["controller"], "pending_addition": True},
                {"roles": ["controller", "cinder"], "pending_addition": True},
                {"roles": ["compute", "cinder"], "pending_addition": True},
                {"roles": ["compute"], "pending_addition": True},
                {"roles": ["cinder"], "pending_addition": True},
            ],
        )

        cluster_db = self.env.clusters[0]

        common_attrs = {
            "deployment_mode": "ha_compact",
            "management_vip": "192.168.0.2",
            "public_vip": "172.16.0.2",
            "fixed_network_range": "10.0.0.0/16",
            "management_network_range": "192.168.0.0/24",
            "floating_network_range": ["172.16.0.128-172.16.0.254"],
            "storage_network_range": "192.168.1.0/24",
            "mp": [{"weight": "1", "point": "1"}, {"weight": "2", "point": "2"}],
            "novanetwork_parameters": {"network_manager": "FlatDHCPManager", "network_size": 256},
            "dns_nameservers": ["8.8.8.8", "8.8.4.4"],
            "management_interface": "eth0.101",
            "fixed_interface": "eth0.103",
            "admin_interface": "eth1",
            "storage_interface": "eth0.102",
            "public_interface": "eth0",
            "floating_interface": "eth0",
            "master_ip": "127.0.0.1",
            "use_cinder": True,
            "deployment_id": cluster_db.id,
        }

        cluster_attrs = cluster_db.attributes.merged_attrs_values()
        common_attrs.update(cluster_attrs)

        # Common attrs calculation
        nodes_list = []
        nodes_db = sorted(cluster_db.nodes, key=lambda n: n.id)
        assigned_ips = {}
        i = 0
        admin_ips = [
            "10.20.0.139/24",
            "10.20.0.138/24",
            "10.20.0.135/24",
            "10.20.0.133/24",
            "10.20.0.131/24",
            "10.20.0.130/24",
        ]
        for node in nodes_db:
            node_id = node.id
            admin_ip = admin_ips.pop()
            for role in sorted(node.roles + node.pending_roles):
                assigned_ips[node_id] = {}
                assigned_ips[node_id]["internal"] = "192.168.0.%d" % (i + 3)
                assigned_ips[node_id]["public"] = "172.16.0.%d" % (i + 3)
                assigned_ips[node_id]["storage"] = "192.168.1.%d" % (i + 2)
                assigned_ips[node_id]["admin"] = admin_ip

                nodes_list.append(
                    {
                        "role": role,
                        "internal_address": assigned_ips[node_id]["internal"],
                        "public_address": assigned_ips[node_id]["public"],
                        "storage_address": assigned_ips[node_id]["storage"],
                        "internal_netmask": "255.255.255.0",
                        "public_netmask": "255.255.255.0",
                        "storage_netmask": "255.255.255.0",
                        "uid": str(node_id),
                        "swift_zone": str(node_id),
                        "name": "node-%d" % node_id,
                        "fqdn": "node-%d.%s" % (node_id, settings.DNS_DOMAIN),
                    }
                )
            i += 1

        controller_nodes = filter(lambda node: node["role"] == "controller", deepcopy(nodes_list))

        common_attrs["nodes"] = nodes_list
        common_attrs["nodes"][0]["role"] = "primary-controller"

        common_attrs["last_controller"] = controller_nodes[-1]["name"]

        # Individual attrs calculation and
        # merging with common attrs
        priority_mapping = {"controller": [600, 500, 400], "cinder": 700, "compute": 700}

        deployment_info = []
        for node in nodes_db:
            ips = assigned_ips[node.id]
            for role in sorted(node.roles):
                priority = priority_mapping[role]
                if isinstance(priority, list):
                    priority = priority.pop()

                individual_atts = {
                    "uid": str(node.id),
                    "status": node.status,
                    "role": role,
                    "online": node.online,
                    "fqdn": "node-%d.%s" % (node.id, settings.DNS_DOMAIN),
                    "priority": priority,
                    "network_data": {
                        "eth0": {"interface": "eth0", "ipaddr": ["%s/24" % ips["public"]], "gateway": "172.16.0.1"},
                        "eth0.101": {"interface": "eth0.101", "ipaddr": ["%s/24" % ips["internal"]]},
                        "eth0.102": {"interface": "eth0.102", "ipaddr": ["%s/24" % ips["storage"]]},
                        "eth0.103": {"interface": "eth0.103", "ipaddr": "none"},
                        "lo": {"interface": "lo", "ipaddr": ["127.0.0.1/8"]},
                        "eth1": {"interface": "eth1", "ipaddr": [ips["admin"]]},
                    },
                }

                individual_atts.update(common_attrs)
                individual_atts["glance"]["image_cache_max_size"] = str(
                    manager.calc_glance_cache_size(node.attributes.volumes)
                )
                deployment_info.append(deepcopy(individual_atts))

        controller_nodes = filter(lambda node: node["role"] == "controller", deployment_info)
        controller_nodes[0]["role"] = "primary-controller"

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [x.uuid for x in supertask.subtasks if x.name == "deployment"][0]

        deployment_msg = {"method": "deploy", "respond_to": "deploy_resp", "args": {}}

        deployment_msg["args"]["task_uuid"] = deploy_task_uuid
        deployment_msg["args"]["deployment_info"] = deployment_info

        provision_nodes = []
        admin_net = self.env.network_manager.get_admin_network()

        for n in sorted(self.env.nodes, key=lambda n: n.id):
            udev_interfaces_mapping = ",".join(["{0}_{1}".format(i.mac, i.name) for i in n.interfaces])

            pnd = {
                "profile": cluster_attrs["cobbler"]["profile"],
                "power_type": "ssh",
                "power_user": "******",
                "kernel_options": {"netcfg/choose_interface": "eth1", "udevrules": udev_interfaces_mapping},
                "power_address": n.ip,
                "power_pass": settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                "name": TaskHelper.make_slave_name(n.id),
                "hostname": n.fqdn,
                "name_servers": '"%s"' % settings.DNS_SERVERS,
                "name_servers_search": '"%s"' % settings.DNS_SEARCH,
                "netboot_enabled": "1",
                "ks_meta": {
                    "puppet_auto_setup": 1,
                    "puppet_master": settings.PUPPET_MASTER_HOST,
                    "puppet_version": settings.PUPPET_VERSION,
                    "puppet_enable": 0,
                    "mco_auto_setup": 1,
                    "install_log_2_syslog": 1,
                    "mco_pskey": settings.MCO_PSKEY,
                    "mco_vhost": settings.MCO_VHOST,
                    "mco_host": settings.MCO_HOST,
                    "mco_user": settings.MCO_USER,
                    "mco_password": settings.MCO_PASSWORD,
                    "mco_connector": settings.MCO_CONNECTOR,
                    "mco_enable": 1,
                    "ks_spaces": n.attributes.volumes,
                    "auth_key": '"%s"' % cluster_attrs.get("auth_key", ""),
                },
            }

            NetworkManager.assign_admin_ips(n.id, len(n.meta.get("interfaces", [])))

            admin_ips = set(
                [i.ip_addr for i in self.db.query(IPAddr).filter_by(node=n.id).filter_by(network=admin_net.id)]
            )

            for i in n.meta.get("interfaces", []):
                if "interfaces" not in pnd:
                    pnd["interfaces"] = {}
                pnd["interfaces"][i["name"]] = {
                    "mac_address": i["mac"],
                    "static": "0",
                    "netmask": admin_net.network_group.netmask,
                    "ip_address": admin_ips.pop(),
                }
                if "interfaces_extra" not in pnd:
                    pnd["interfaces_extra"] = {}
                pnd["interfaces_extra"][i["name"]] = {"peerdns": "no", "onboot": "no"}

                if i["mac"] == n.mac:
                    pnd["interfaces"][i["name"]]["dns_name"] = n.fqdn
                    pnd["interfaces_extra"][i["name"]]["onboot"] = "yes"

            provision_nodes.append(pnd)

        provision_task_uuid = filter(lambda t: t.name == "provision", supertask.subtasks)[0].uuid

        provision_msg = {
            "method": "provision",
            "respond_to": "provision_resp",
            "args": {
                "task_uuid": provision_task_uuid,
                "provisioning_info": {
                    "engine": {
                        "url": settings.COBBLER_URL,
                        "username": settings.COBBLER_USER,
                        "password": settings.COBBLER_PASSWORD,
                    },
                    "nodes": provision_nodes,
                },
            },
        }

        args, kwargs = nailgun.task.manager.rpc.cast.call_args
        self.assertEquals(len(args), 2)
        self.assertEquals(len(args[1]), 2)

        self.datadiff(args[1][0], provision_msg)
        self.datadiff(args[1][1], deployment_msg)
Example #26
0
    def execute(self, task, respond_to='remove_nodes_resp'):
        logger.debug("DeletionTask.execute(task=%s)" % task.uuid)
        task_uuid = task.uuid
        logger.debug("Nodes deletion task is running")
        nodes_to_delete = []
        nodes_to_delete_constant = []
        nodes_to_restore = []

        USE_FAKE = settings.FAKE_TASKS or settings.FAKE_TASKS_AMQP

        # no need to call astute if there are no nodes in cluster
        if respond_to == 'remove_cluster_resp' and \
                not list(task.cluster.nodes):
            rcvr = rpc.receiver.NailgunReceiver()
            rcvr.remove_cluster_resp(task_uuid=task_uuid,
                                     status='ready',
                                     progress=100)
            return

        for node in task.cluster.nodes:
            if node.pending_deletion:
                nodes_to_delete.append({
                    'id':
                    node.id,
                    'uid':
                    node.id,
                    'roles':
                    node.roles,
                    'slave_name':
                    TaskHelper.make_slave_name(node.id)
                })

                if USE_FAKE:
                    # only fake tasks
                    new_node = {}
                    keep_attrs = ('id', 'cluster_id', 'roles',
                                  'pending_deletion', 'pending_addition')
                    for prop in object_mapper(node).iterate_properties:
                        if isinstance(
                                prop,
                                ColumnProperty) and prop.key not in keep_attrs:
                            new_node[prop.key] = getattr(node, prop.key)
                    nodes_to_restore.append(new_node)
                    # /only fake tasks

        # this variable is used to iterate over it
        # and be able to delete node from nodes_to_delete safely
        nodes_to_delete_constant = list(nodes_to_delete)

        for node in nodes_to_delete_constant:
            node_db = db().query(Node).get(node['id'])

            slave_name = TaskHelper.make_slave_name(node['id'])
            logger.debug(
                "Removing node from database and pending it "
                "to clean its MBR: %s", slave_name)
            if node_db.status == 'discover':
                logger.info("Node is not deployed yet,"
                            " can't clean MBR: %s", slave_name)
                db().delete(node_db)
                db().commit()

                nodes_to_delete.remove(node)

        msg_delete = make_astute_message(
            'remove_nodes', respond_to, {
                'task_uuid': task.uuid,
                'nodes': nodes_to_delete,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                    'master_ip': settings.MASTER_IP,
                }
            })
        # only fake tasks
        if USE_FAKE and nodes_to_restore:
            msg_delete['args']['nodes_to_restore'] = nodes_to_restore
        # /only fake tasks
        logger.debug("Calling rpc remove_nodes method")
        rpc.cast('naily', msg_delete)
    def test_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(
            cluster_kwargs={
                'mode': 'ha_compact'
            },
            nodes_kwargs=[
                {'roles': ['controller'], 'pending_addition': True},
                {'roles': ['controller'], 'pending_addition': True},
                {'roles': ['controller', 'cinder'], 'pending_addition': True},
                {'roles': ['compute', 'cinder'], 'pending_addition': True},
                {'roles': ['compute'], 'pending_addition': True},
                {'roles': ['cinder'], 'pending_addition': True}])

        cluster_db = self.env.clusters[0]

        common_attrs = {
            'deployment_mode': 'ha_compact',
            'mountpoints': '1 1\\n2 2\\n',

            'management_vip': '192.168.0.2',
            'public_vip': '172.16.1.2',

            'fixed_network_range': '10.0.0.0/24',
            'management_network_range': '192.168.0.0/24',
            'floating_network_range': ['172.16.0.2-172.16.0.254'],
            'storage_network_range': '192.168.1.0/24',

            'mp': [{'weight': '1', 'point': '1'},
                   {'weight': '2', 'point': '2'}],
            'novanetwork_parameters': {
                'network_manager': 'FlatDHCPManager',
                'network_size': 256
            },

            'management_interface': 'eth0.101',
            'fixed_interface': 'eth0.103',
            'admin_interface': 'eth0',
            'storage_interface': 'eth0.102',
            'public_interface': 'eth0.100',
            'floating_interface': 'eth0.100',

            'master_ip': '127.0.0.1',
            'use_cinder': True,
            'deployment_id': cluster_db.id
        }

        cluster_attrs = cluster_db.attributes.merged_attrs_values()
        common_attrs.update(cluster_attrs)

        # Common attrs calculation
        nodes_list = []
        nodes_db = sorted(cluster_db.nodes, key=lambda n: n.id)
        assigned_ips = {}
        i = 0
        for node in nodes_db:
            node_id = node.id
            for role in sorted(node.roles + node.pending_roles):
                assigned_ips[node_id] = {}
                assigned_ips[node_id]['internal'] = '192.168.0.%d' % (i + 3)
                assigned_ips[node_id]['public'] = '172.16.1.%d' % (i + 3)
                assigned_ips[node_id]['storage'] = '192.168.1.%d' % (i + 2)

                nodes_list.append({
                    'role': role,

                    'internal_address': assigned_ips[node_id]['internal'],
                    'public_address': assigned_ips[node_id]['public'],
                    'storage_address': assigned_ips[node_id]['storage'],

                    'internal_netmask': '255.255.255.0',
                    'public_netmask': '255.255.255.0',
                    'storage_netmask': '255.255.255.0',

                    'uid': str(node_id),
                    'swift_zone': str(node_id),

                    'name': 'node-%d' % node_id,
                    'fqdn': 'node-%d.%s' % (node_id, settings.DNS_DOMAIN)})
            i += 1

        common_attrs['controller_nodes'] = filter(
            lambda node: node['role'] == 'controller',
            deepcopy(nodes_list))

        common_attrs['nodes'] = nodes_list
        common_attrs['nodes'][0]['role'] = 'primary-controller'

        common_attrs['last_controller'] = common_attrs[
            'controller_nodes'][-1]['name']

        # Individual attrs calculation and
        # merging with common attrs
        priority_mapping = {
            'controller': [600, 500, 400],
            'cinder': 700,
            'compute': 700
        }

        deployment_info = []
        for node in nodes_db:
            ips = assigned_ips[node.id]
            for role in sorted(node.roles):
                priority = priority_mapping[role]
                if isinstance(priority, list):
                    priority = priority.pop()

                individual_atts = {
                    'uid': str(node.id),
                    'status': node.status,
                    'role': role,
                    'online': node.online,
                    'fqdn': 'node-%d.%s' % (node.id, settings.DNS_DOMAIN),
                    'priority': priority,

                    'network_data': {
                        'eth0.100': {
                            'interface': 'eth0.100',
                            'ipaddr': ['%s/24' % ips['public']],
                            'gateway': '172.16.1.1',
                            '_name': 'public'},
                        'eth0.101': {
                            'interface': 'eth0.101',
                            'ipaddr': ['%s/24' % ips['internal']],
                            '_name': 'management'},
                        'eth0.102': {
                            'interface': 'eth0.102',
                            'ipaddr': ['%s/24' % ips['storage']],
                            '_name': 'storage'},
                        'eth0.103': {
                            'interface': 'eth0.103',
                            'ipaddr': 'none',
                            '_name': 'fixed'},
                        'lo': {
                            'interface': 'lo',
                            'ipaddr': ['127.0.0.1/8']},
                        'eth1': {
                            'interface': 'eth1',
                            'ipaddr': 'none'},
                        'eth0': {
                            'interface': 'eth0',
                            'ipaddr': 'dhcp',
                            '_name': 'admin'}}}

                individual_atts.update(common_attrs)
                deployment_info.append(individual_atts)

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [x.uuid for x in supertask.subtasks
                            if x.name == 'deployment'][0]

        deployment_msg = {'method': 'deploy',
                          'respond_to': 'deploy_resp',
                          'args': {}}

        deployment_msg['args']['task_uuid'] = deploy_task_uuid
        deployment_msg['args']['deployment_info'] = deployment_info

        provision_nodes = []
        admin_net_id = self.env.network_manager.get_admin_network_id()

        for n in sorted(self.env.nodes, key=lambda n: n.id):
            pnd = {
                'profile': cluster_attrs['cobbler']['profile'],
                'power_type': 'ssh',
                'power_user': '******',
                'power_address': n.ip,
                'power_pass': settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                'name': TaskHelper.make_slave_name(n.id),
                'hostname': n.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'ks_spaces': "\"%s\"" % json.dumps(
                        n.attributes.volumes).replace("\"", "\\\""),
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                }
            }

            netmanager = NetworkManager()
            netmanager.assign_admin_ips(
                n.id,
                len(n.meta.get('interfaces', []))
            )

            admin_ips = set([i.ip_addr for i in self.db.query(IPAddr).
                            filter_by(node=n.id).
                            filter_by(network=admin_net_id)])

            for i in n.meta.get('interfaces', []):
                if 'interfaces' not in pnd:
                    pnd['interfaces'] = {}
                pnd['interfaces'][i['name']] = {
                    'mac_address': i['mac'],
                    'static': '0',
                    'netmask': settings.ADMIN_NETWORK['netmask'],
                    'ip_address': admin_ips.pop(),
                }
                if 'interfaces_extra' not in pnd:
                    pnd['interfaces_extra'] = {}
                pnd['interfaces_extra'][i['name']] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                if i['mac'] == n.mac:
                    pnd['interfaces'][i['name']]['dns_name'] = n.fqdn
                    pnd['interfaces_extra'][i['name']]['onboot'] = 'yes'

            provision_nodes.append(pnd)

        provision_task_uuid = filter(
            lambda t: t.name == 'provision',
            supertask.subtasks)[0].uuid

        provision_msg = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': provision_task_uuid,
                'provisioning_info': {
                    'engine': {
                        'url': settings.COBBLER_URL,
                        'username': settings.COBBLER_USER,
                        'password': settings.COBBLER_PASSWORD},
                    'nodes': provision_nodes}}}

        args, kwargs = nailgun.task.manager.rpc.cast.call_args
        self.assertEquals(len(args), 2)
        self.assertEquals(len(args[1]), 2)
        self.datadiff(args[1][0], provision_msg)
        self.datadiff(args[1][1], deployment_msg)
    def test_nova_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(
            nodes_kwargs=[
                {'roles': ['controller'], 'pending_addition': True},
                {'roles': ['controller'], 'pending_addition': True},
                {'roles': ['controller', 'cinder'], 'pending_addition': True},
                {'roles': ['compute', 'cinder'], 'pending_addition': True},
                {'roles': ['compute'], 'pending_addition': True},
                {'roles': ['cinder'], 'pending_addition': True}
            ]
        )

        cluster_db = self.env.clusters[0]

        common_attrs = {
            'deployment_mode': 'ha_compact',

            'management_vip': '192.168.0.1',
            'public_vip': '172.16.0.2',

            'fixed_network_range': '10.0.0.0/16',
            'management_network_range': '192.168.0.0/24',
            'floating_network_range': ['172.16.0.128-172.16.0.254'],
            'storage_network_range': '192.168.1.0/24',

            'mp': [{'weight': '1', 'point': '1'},
                   {'weight': '2', 'point': '2'}],
            'novanetwork_parameters': {
                'network_manager': 'FlatDHCPManager',
                'network_size': 256
            },
            'dns_nameservers': [
                "8.8.8.8",
                "8.8.4.4"
            ],

            'management_interface': 'eth0.101',
            'fixed_interface': 'eth0.103',
            'admin_interface': 'eth1',
            'storage_interface': 'eth0.102',
            'public_interface': 'eth0',
            'floating_interface': 'eth0',

            'master_ip': '127.0.0.1',
            'use_cinder': True,
            'deployment_id': cluster_db.id
        }

        cluster_attrs = objects.Attributes.merged_attrs_values(
            cluster_db.attributes
        )
        common_attrs.update(cluster_attrs)

        # Common attrs calculation
        nodes_list = []
        nodes_db = sorted(cluster_db.nodes, key=lambda n: n.id)
        assigned_ips = {}
        i = 0
        admin_ips = [
            '10.20.0.134/24',
            '10.20.0.133/24',
            '10.20.0.132/24',
            '10.20.0.131/24',
            '10.20.0.130/24',
            '10.20.0.129/24']
        for node in nodes_db:
            node_id = node.id
            admin_ip = admin_ips.pop()
            for role in sorted(node.roles + node.pending_roles):
                assigned_ips[node_id] = {}
                assigned_ips[node_id]['internal'] = '192.168.0.%d' % (i + 2)
                assigned_ips[node_id]['public'] = '172.16.0.%d' % (i + 3)
                assigned_ips[node_id]['storage'] = '192.168.1.%d' % (i + 1)
                assigned_ips[node_id]['admin'] = admin_ip

                nodes_list.append({
                    'role': role,

                    'internal_address': assigned_ips[node_id]['internal'],
                    'public_address': assigned_ips[node_id]['public'],
                    'storage_address': assigned_ips[node_id]['storage'],

                    'internal_netmask': '255.255.255.0',
                    'public_netmask': '255.255.255.0',
                    'storage_netmask': '255.255.255.0',

                    'uid': str(node_id),
                    'swift_zone': str(node_id),

                    'name': 'node-%d' % node_id,
                    'fqdn': 'node-%d.%s' % (node_id, settings.DNS_DOMAIN)})
            i += 1

        controller_nodes = filter(
            lambda node: node['role'] == 'controller',
            deepcopy(nodes_list))

        common_attrs['nodes'] = nodes_list
        common_attrs['nodes'][0]['role'] = 'primary-controller'

        common_attrs['last_controller'] = controller_nodes[-1]['name']
        common_attrs['storage']['pg_num'] = 128

        # Individual attrs calculation and
        # merging with common attrs
        priority_mapping = {
            'controller': [600, 500, 400],
            'cinder': 700,
            'compute': 700
        }

        deployment_info = []
        for node in nodes_db:
            ips = assigned_ips[node.id]
            for role in sorted(node.roles):
                priority = priority_mapping[role]
                if isinstance(priority, list):
                    priority = priority.pop()

                individual_atts = {
                    'uid': str(node.id),
                    'status': node.status,
                    'role': role,
                    'online': node.online,
                    'fqdn': 'node-%d.%s' % (node.id, settings.DNS_DOMAIN),
                    'priority': priority,

                    'network_data': {
                        'eth0': {
                            'interface': 'eth0',
                            'ipaddr': ['%s/24' % ips['public']],
                            'gateway': '172.16.0.1'},
                        'eth0.101': {
                            'interface': 'eth0.101',
                            'ipaddr': ['%s/24' % ips['internal']]},
                        'eth0.102': {
                            'interface': 'eth0.102',
                            'ipaddr': ['%s/24' % ips['storage']]},
                        'eth0.103': {
                            'interface': 'eth0.103',
                            'ipaddr': 'none'},
                        'lo': {
                            'interface': 'lo',
                            'ipaddr': ['127.0.0.1/8']},
                        'eth1': {
                            'interface': 'eth1',
                            'ipaddr': [ips['admin']]}
                    }}

                individual_atts.update(common_attrs)
                individual_atts['glance']['image_cache_max_size'] = str(
                    manager.calc_glance_cache_size(node.attributes.volumes)
                )
                deployment_info.append(deepcopy(individual_atts))

        controller_nodes = filter(
            lambda node: node['role'] == 'controller',
            deployment_info)
        controller_nodes[0]['role'] = 'primary-controller'

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [x.uuid for x in supertask.subtasks
                            if x.name == 'deployment'][0]

        deployment_msg = {'method': 'deploy',
                          'respond_to': 'deploy_resp',
                          'args': {}}

        deployment_msg['args']['task_uuid'] = deploy_task_uuid
        deployment_msg['args']['deployment_info'] = deployment_info

        provision_nodes = []
        admin_net = self.env.network_manager.get_admin_network_group()

        for n in sorted(self.env.nodes, key=lambda n: n.id):
            udev_interfaces_mapping = ','.join([
                '{0}_{1}'.format(i.mac, i.name) for i in n.interfaces])
            eth1_mac = [i.mac for i in n.interfaces if i.name == 'eth1'][0]

            pnd = {
                'profile': cluster_attrs['cobbler']['profile'],
                'power_type': 'ssh',
                'power_user': '******',
                'kernel_options': {
                    'netcfg/choose_interface': eth1_mac,
                    'udevrules': udev_interfaces_mapping},
                'power_address': n.ip,
                'power_pass': settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                'name': TaskHelper.make_slave_name(n.id),
                'hostname': n.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'ks_spaces': n.attributes.volumes,
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                }
            }

            vlan_splinters = cluster_attrs.get('vlan_splinters', None)
            if vlan_splinters == 'kernel_lt':
                pnd['ks_meta']['kernel_lt'] = 1

            NetworkManager.assign_admin_ips(n.id, 1)

            admin_ip = self.env.network_manager.get_admin_ip_for_node(n)

            for i in n.interfaces:
                if 'interfaces' not in pnd:
                    pnd['interfaces'] = {}
                pnd['interfaces'][i.name] = {
                    'mac_address': i.mac,
                    'static': '0',
                }
                if 'interfaces_extra' not in pnd:
                    pnd['interfaces_extra'] = {}
                pnd['interfaces_extra'][i.name] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                if i.mac == n.mac:
                    pnd['interfaces'][i.name]['dns_name'] = n.fqdn
                    pnd['interfaces_extra'][i.name]['onboot'] = 'yes'
                    pnd['interfaces'][i.name]['ip_address'] = admin_ip
                    pnd['interfaces'][i.name]['netmask'] = admin_net.netmask

            provision_nodes.append(pnd)

        provision_task_uuid = filter(
            lambda t: t.name == 'provision',
            supertask.subtasks)[0].uuid

        provision_msg = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': provision_task_uuid,
                'provisioning_info': {
                    'engine': {
                        'url': settings.COBBLER_URL,
                        'username': settings.COBBLER_USER,
                        'password': settings.COBBLER_PASSWORD},
                    'nodes': provision_nodes}}}

        args, kwargs = nailgun.task.manager.rpc.cast.call_args
        self.assertEquals(len(args), 2)
        self.assertEquals(len(args[1]), 2)

        self.datadiff(args[1][0], provision_msg)
        self.datadiff(args[1][1], deployment_msg)
    def test_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(
            cluster_kwargs={
                "mode": "ha",
                "type": "compute"
            },
            nodes_kwargs=[
                {"role": "controller", "pending_addition": True},
                {"role": "controller", "pending_addition": True},
                {"role": "controller", "pending_addition": True},
            ]
        )
        cluster_db = self.env.clusters[0]
        cluster_depl_mode = 'ha'

        # Set ip ranges for floating ips
        ranges = [['240.0.0.2', '240.0.0.4'],
                  ['240.0.0.3', '240.0.0.5'],
                  ['240.0.0.10', '240.0.0.12']]

        floating_network_group = self.db.query(NetworkGroup).filter(
            NetworkGroup.name == 'floating').filter(
                NetworkGroup.cluster_id == cluster_db.id).first()

        # Remove floating ip addr ranges
        self.db.query(IPAddrRange).filter(
            IPAddrRange.network_group_id == floating_network_group.id).delete()

        # Add new ranges
        for ip_range in ranges:
            new_ip_range = IPAddrRange(
                first=ip_range[0],
                last=ip_range[1],
                network_group_id=floating_network_group.id)

            self.db.add(new_ip_range)
        self.db.commit()

        # Update netmask for public network
        public_network_group = self.db.query(NetworkGroup).filter(
            NetworkGroup.name == 'public').filter(
                NetworkGroup.cluster_id == cluster_db.id).first()
        public_network_group.netmask = '255.255.255.128'
        self.db.commit()

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [x.uuid for x in supertask.subtasks
                            if x.name == 'deployment'][0]

        msg = {'method': 'deploy', 'respond_to': 'deploy_resp',
               'args': {}}
        self.db.add(cluster_db)
        cluster_attrs = cluster_db.attributes.merged_attrs_values()

        nets_db = self.db.query(Network).join(NetworkGroup).\
            filter(NetworkGroup.cluster_id == cluster_db.id).all()

        for net in nets_db:
            if net.name != 'public':
                cluster_attrs[net.name + '_network_range'] = net.cidr

        cluster_attrs['floating_network_range'] = [
            '240.0.0.10',
            '240.0.0.11',
            '240.0.0.12',

            '240.0.0.2',
            '240.0.0.3',
            '240.0.0.4',
            '240.0.0.5']

        management_vip = self.env.network_manager.assign_vip(
            cluster_db.id,
            'management'
        )
        public_vip = self.env.network_manager.assign_vip(
            cluster_db.id,
            'public'
        )

        cluster_attrs['management_vip'] = management_vip
        cluster_attrs['public_vip'] = public_vip
        cluster_attrs['deployment_mode'] = cluster_depl_mode
        cluster_attrs['deployment_id'] = cluster_db.id
        cluster_attrs['network_manager'] = "FlatDHCPManager"
        cluster_attrs['network_size'] = 256

        msg['args']['attributes'] = cluster_attrs
        msg['args']['task_uuid'] = deploy_task_uuid
        nodes = []
        provision_nodes = []

        admin_net_id = self.env.network_manager.get_admin_network_id()

        for n in sorted(self.env.nodes, key=lambda n: n.id):

            q = self.db.query(IPAddr).join(Network).\
                filter(IPAddr.node == n.id).filter(
                    not_(IPAddr.network == admin_net_id)
                )

            """
            Here we want to get node IP addresses which belong
            to storage and management networks respectively
            """
            node_ip_management, node_ip_storage = map(
                lambda x: q.filter_by(name=x).first().ip_addr
                + "/" + cluster_attrs[x + '_network_range'].split('/')[1],
                ('management', 'storage')
            )
            node_ip_public = q.filter_by(name='public').first().ip_addr + '/25'

            nodes.append({'uid': n.id, 'status': n.status, 'ip': n.ip,
                          'error_type': n.error_type, 'mac': n.mac,
                          'role': n.role, 'id': n.id, 'fqdn':
                          '%s-%d.%s' % (n.role, n.id, settings.DNS_DOMAIN),
                          'progress': 0, 'meta': n.meta, 'online': True,
                          'network_data': [{'brd': '192.168.0.255',
                                            'ip': node_ip_management,
                                            'vlan': 103,
                                            'gateway': '192.168.0.1',
                                            'netmask': '255.255.255.0',
                                            'dev': 'eth0',
                                            'name': 'management'},
                                           {'brd': '240.0.1.255',
                                            'ip': node_ip_public,
                                            'vlan': 100,
                                            'gateway': '240.0.1.1',
                                            'netmask': '255.255.255.128',
                                            'dev': 'eth0',
                                            'name': u'public'},
                                           {'name': u'storage',
                                            'ip': node_ip_storage,
                                            'vlan': 102,
                                            'dev': 'eth0',
                                            'netmask': '255.255.255.0',
                                            'brd': '172.16.0.255',
                                            'gateway': u'172.16.0.1'},
                                           {'vlan': 100,
                                            'name': 'floating',
                                            'dev': 'eth0'},
                                           {'vlan': 101,
                                            'name': 'fixed',
                                            'dev': 'eth0'},
                                           {'name': u'admin',
                                            'dev': 'eth0'}]})

            pnd = {
                'profile': cluster_attrs['cobbler']['profile'],
                'power_type': 'ssh',
                'power_user': '******',
                'power_address': n.ip,
                'power_pass': settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                'name': TaskHelper.make_slave_name(n.id, n.role),
                'hostname': n.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'ks_spaces': "\"%s\"" % json.dumps(
                        n.attributes.volumes).replace("\"", "\\\""),
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                }
            }

            netmanager = NetworkManager()
            netmanager.assign_admin_ips(
                n.id,
                len(n.meta.get('interfaces', []))
            )

            admin_ips = set([i.ip_addr for i in self.db.query(IPAddr).
                            filter_by(node=n.id).
                            filter_by(network=admin_net_id)])

            for i in n.meta.get('interfaces', []):
                if 'interfaces' not in pnd:
                    pnd['interfaces'] = {}
                pnd['interfaces'][i['name']] = {
                    'mac_address': i['mac'],
                    'static': '0',
                    'netmask': settings.ADMIN_NETWORK['netmask'],
                    'ip_address': admin_ips.pop(),
                }
                if 'interfaces_extra' not in pnd:
                    pnd['interfaces_extra'] = {}
                pnd['interfaces_extra'][i['name']] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                if i['mac'] == n.mac:
                    pnd['interfaces'][i['name']]['dns_name'] = n.fqdn
                    pnd['interfaces_extra'][i['name']]['onboot'] = 'yes'

            provision_nodes.append(pnd)

        controller_nodes = filter(
            lambda node: node['role'] == 'controller',
            nodes)
        msg['args']['attributes']['controller_nodes'] = controller_nodes
        msg['args']['nodes'] = nodes

        provision_task_uuid = [x.uuid for x in supertask.subtasks
                               if x.name == 'provision'][0]
        provision_msg = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': provision_task_uuid,
                'engine': {
                    'url': settings.COBBLER_URL,
                    'username': settings.COBBLER_USER,
                    'password': settings.COBBLER_PASSWORD,
                },
                'nodes': provision_nodes,
            }
        }

        nailgun.task.manager.rpc.cast.assert_called_once_with(
            'naily', [provision_msg, msg])
    def test_neutron_deploy_cast_with_right_args(self, mocked_rpc):
        self.env.create(cluster_kwargs={
            'mode': 'ha_compact',
            'net_provider': 'neutron',
            'net_segment_type': 'gre'
        },
                        nodes_kwargs=[{
                            'roles': ['controller'],
                            'pending_addition': True
                        }, {
                            'roles': ['controller'],
                            'pending_addition': True
                        }, {
                            'roles': ['controller', 'cinder'],
                            'pending_addition': True
                        }, {
                            'roles': ['compute', 'cinder'],
                            'pending_addition': True
                        }, {
                            'roles': ['compute'],
                            'pending_addition': True
                        }, {
                            'roles': ['cinder'],
                            'pending_addition': True
                        }])

        cluster_db = self.env.clusters[0]

        common_attrs = {
            'deployment_mode': 'ha_compact',
            'management_vip': '192.168.0.2',
            'public_vip': '172.16.0.2',
            'management_network_range': '192.168.0.0/24',
            'storage_network_range': '192.168.1.0/24',
            'mp': [{
                'weight': '1',
                'point': '1'
            }, {
                'weight': '2',
                'point': '2'
            }],
            'quantum': True,
            'quantum_settings': {},
            'master_ip': '127.0.0.1',
            'use_cinder': True,
            'deployment_id': cluster_db.id
        }

        cluster_attrs = cluster_db.attributes.merged_attrs_values()
        common_attrs.update(cluster_attrs)

        L2 = {
            "base_mac": "fa:16:3e:00:00:00",
            "segmentation_type": "gre",
            "phys_nets": {
                "physnet1": {
                    "bridge": "br-ex",
                    "vlan_range": None
                },
                "physnet2": {
                    "bridge": "br-prv",
                    "vlan_range": None
                }
            },
            "tunnel_id_ranges": "2:65535"
        }
        L3 = {"use_namespaces": True}
        predefined_networks = {
            "net04_ext": {
                'shared': False,
                'L2': {
                    'router_ext': True,
                    'network_type': 'flat',
                    'physnet': 'physnet1',
                    'segment_id': None
                },
                'L3': {
                    'subnet': u'172.16.0.0/24',
                    'enable_dhcp': False,
                    'nameservers': [],
                    'floating': '172.16.0.130:172.16.0.254',
                    'gateway': '172.16.0.1'
                },
                'tenant': 'admin'
            },
            "net04": {
                'shared': False,
                'L2': {
                    'router_ext': False,
                    'network_type': 'gre',
                    'physnet': 'physnet2',
                    'segment_id': None
                },
                'L3': {
                    'subnet': u'192.168.111.0/24',
                    'enable_dhcp': True,
                    'nameservers': ['8.8.4.4', '8.8.8.8'],
                    'floating': None,
                    'gateway': '192.168.111.1'
                },
                'tenant': 'admin'
            }
        }
        common_attrs['quantum_settings'].update(
            L2=L2, L3=L3, predefined_networks=predefined_networks)

        # Common attrs calculation
        nodes_list = []
        nodes_db = sorted(cluster_db.nodes, key=lambda n: n.id)
        assigned_ips = {}
        i = 0
        admin_ips = [
            '10.20.0.139/24', '10.20.0.138/24', '10.20.0.135/24',
            '10.20.0.133/24', '10.20.0.131/24', '10.20.0.130/24'
        ]
        for node in nodes_db:
            node_id = node.id
            admin_ip = admin_ips.pop()
            for role in sorted(node.roles + node.pending_roles):
                assigned_ips[node_id] = {}
                assigned_ips[node_id]['management'] = '192.168.0.%d' % (i + 3)
                assigned_ips[node_id]['public'] = '172.16.0.%d' % (i + 3)
                assigned_ips[node_id]['storage'] = '192.168.1.%d' % (i + 2)
                assigned_ips[node_id]['admin'] = admin_ip

                nodes_list.append({
                    'role':
                    role,
                    'internal_address':
                    assigned_ips[node_id]['management'],
                    'public_address':
                    assigned_ips[node_id]['public'],
                    'storage_address':
                    assigned_ips[node_id]['storage'],
                    'internal_netmask':
                    '255.255.255.0',
                    'public_netmask':
                    '255.255.255.0',
                    'storage_netmask':
                    '255.255.255.0',
                    'uid':
                    str(node_id),
                    'swift_zone':
                    str(node_id),
                    'name':
                    'node-%d' % node_id,
                    'fqdn':
                    'node-%d.%s' % (node_id, settings.DNS_DOMAIN)
                })
            i += 1

        controller_nodes = filter(lambda node: node['role'] == 'controller',
                                  deepcopy(nodes_list))

        common_attrs['nodes'] = nodes_list
        common_attrs['nodes'][0]['role'] = 'primary-controller'

        common_attrs['last_controller'] = controller_nodes[-1]['name']

        # Individual attrs calculation and
        # merging with common attrs
        priority_mapping = {
            'controller': [600, 500, 400],
            'cinder': 700,
            'compute': 700
        }
        deployment_info = []
        for node in nodes_db:
            ips = assigned_ips[node.id]
            for role in sorted(node.roles):
                priority = priority_mapping[role]
                if isinstance(priority, list):
                    priority = priority.pop()

                individual_atts = {
                    'uid': str(node.id),
                    'status': node.status,
                    'role': role,
                    'online': node.online,
                    'fqdn': 'node-%d.%s' % (node.id, settings.DNS_DOMAIN),
                    'priority': priority,
                    'network_scheme': {
                        "version":
                        "1.0",
                        "provider":
                        "ovs",
                        "interfaces": {
                            "eth0": {
                                "L2": {
                                    "vlan_splinters": "off"
                                },
                                "mtu": 1500
                            },
                            "eth1": {
                                "L2": {
                                    "vlan_splinters": "off"
                                },
                                "mtu": 1500
                            },
                            "eth2": {
                                "L2": {
                                    "vlan_splinters": "off"
                                },
                                "mtu": 1500
                            },
                        },
                        "endpoints": {
                            "br-mgmt": {
                                "IP": [ips['management'] + "/24"]
                            },
                            "br-ex": {
                                "IP": [ips['public'] + "/24"],
                                "gateway": "172.16.0.1"
                            },
                            "br-storage": {
                                "IP": [ips['storage'] + "/24"]
                            },
                            "eth1": {
                                "IP": [ips['admin']]
                            }
                        },
                        "roles": {
                            "management": "br-mgmt",
                            "mesh": "br-mgmt",
                            "ex": "br-ex",
                            "storage": "br-storage",
                            "fw-admin": "eth1"
                        },
                        "transformations": [{
                            "action": "add-br",
                            "name": "br-ex"
                        }, {
                            "action": "add-br",
                            "name": "br-mgmt"
                        }, {
                            "action": "add-br",
                            "name": "br-storage"
                        }, {
                            "action": "add-br",
                            "name": "br-prv"
                        }, {
                            "action": "add-br",
                            "name": u"br-eth0"
                        }, {
                            "action": "add-port",
                            "bridge": u"br-eth0",
                            "name": u"eth0"
                        }, {
                            "action":
                            "add-patch",
                            "bridges": [u"br-eth0", "br-storage"],
                            "tags": [101, 0]
                        }, {
                            "action": "add-patch",
                            "bridges": [u"br-eth0", "br-ex"],
                            "trunks": [0]
                        }, {
                            "action": "add-patch",
                            "bridges": [u"br-eth0", "br-mgmt"],
                            "tags": [100, 0]
                        }]
                    }
                }

                individual_atts.update(common_attrs)
                individual_atts['glance']['image_cache_max_size'] = str(
                    manager.calc_glance_cache_size(node.attributes.volumes))
                deployment_info.append(deepcopy(individual_atts))

        controller_nodes = filter(lambda node: node['role'] == 'controller',
                                  deployment_info)
        controller_nodes[0]['role'] = 'primary-controller'

        supertask = self.env.launch_deployment()
        deploy_task_uuid = [
            x.uuid for x in supertask.subtasks if x.name == 'deployment'
        ][0]

        deployment_msg = {
            'method': 'deploy',
            'respond_to': 'deploy_resp',
            'args': {}
        }

        deployment_msg['args']['task_uuid'] = deploy_task_uuid
        deployment_msg['args']['deployment_info'] = deployment_info

        provision_nodes = []
        admin_net = self.env.network_manager.get_admin_network_group()

        for n in sorted(self.env.nodes, key=lambda n: n.id):
            udev_interfaces_mapping = ','.join(
                ['{0}_{1}'.format(i.mac, i.name) for i in n.interfaces])

            pnd = {
                'profile': cluster_attrs['cobbler']['profile'],
                'power_type': 'ssh',
                'power_user': '******',
                'kernel_options': {
                    'netcfg/choose_interface': 'eth1',
                    'udevrules': udev_interfaces_mapping
                },
                'power_address': n.ip,
                'power_pass': settings.PATH_TO_BOOTSTRAP_SSH_KEY,
                'name': TaskHelper.make_slave_name(n.id),
                'hostname': n.fqdn,
                'name_servers': '\"%s\"' % settings.DNS_SERVERS,
                'name_servers_search': '\"%s\"' % settings.DNS_SEARCH,
                'netboot_enabled': '1',
                'ks_meta': {
                    'puppet_auto_setup': 1,
                    'puppet_master': settings.PUPPET_MASTER_HOST,
                    'puppet_version': settings.PUPPET_VERSION,
                    'puppet_enable': 0,
                    'mco_auto_setup': 1,
                    'install_log_2_syslog': 1,
                    'mco_pskey': settings.MCO_PSKEY,
                    'mco_vhost': settings.MCO_VHOST,
                    'mco_host': settings.MCO_HOST,
                    'mco_user': settings.MCO_USER,
                    'mco_password': settings.MCO_PASSWORD,
                    'mco_connector': settings.MCO_CONNECTOR,
                    'mco_enable': 1,
                    'ks_spaces': n.attributes.volumes,
                    'auth_key': "\"%s\"" % cluster_attrs.get('auth_key', ''),
                }
            }

            NetworkManager.assign_admin_ips(n.id,
                                            len(n.meta.get('interfaces', [])))

            admin_ips = set([
                i.ip_addr for i in self.db.query(IPAddr).filter_by(
                    node=n.id).filter_by(network=admin_net.id)
            ])

            for i in n.meta.get('interfaces', []):
                if 'interfaces' not in pnd:
                    pnd['interfaces'] = {}
                pnd['interfaces'][i['name']] = {
                    'mac_address': i['mac'],
                    'static': '0',
                    'netmask': admin_net.netmask,
                    'ip_address': admin_ips.pop(),
                }
                if 'interfaces_extra' not in pnd:
                    pnd['interfaces_extra'] = {}
                pnd['interfaces_extra'][i['name']] = {
                    'peerdns': 'no',
                    'onboot': 'no'
                }

                if i['mac'] == n.mac:
                    pnd['interfaces'][i['name']]['dns_name'] = n.fqdn
                    pnd['interfaces_extra'][i['name']]['onboot'] = 'yes'

            provision_nodes.append(pnd)

        provision_task_uuid = filter(lambda t: t.name == 'provision',
                                     supertask.subtasks)[0].uuid

        provision_msg = {
            'method': 'provision',
            'respond_to': 'provision_resp',
            'args': {
                'task_uuid': provision_task_uuid,
                'provisioning_info': {
                    'engine': {
                        'url': settings.COBBLER_URL,
                        'username': settings.COBBLER_USER,
                        'password': settings.COBBLER_PASSWORD
                    },
                    'nodes': provision_nodes
                }
            }
        }

        args, kwargs = nailgun.task.manager.rpc.cast.call_args
        self.assertEquals(len(args), 2)
        self.assertEquals(len(args[1]), 2)

        self.datadiff(args[1][0], provision_msg)
        self.datadiff(args[1][1], deployment_msg)