Esempio n. 1
0
 def test_get_enums(self):
     # This file contains a single enum, named "ENUM".
     enums = get_enums(getsourcefile(TestFunctions))
     self.assertEqual(["ENUM"], [enum.__name__ for enum in enums])
     [enum] = enums
     # Because the module has been executed in a different namespace, the
     # enum we've found is not the same object as the one in the current
     # global namespace.
     self.assertIsNot(ENUM, enum)
     # It does, however, have the same values.
     self.assertEqual(map_enum(ENUM), map_enum(enum))
Esempio n. 2
0
 def test_get_enums(self):
     # This file contains a single enum, named "ENUM".
     enums = get_enums(getsourcefile(TestFunctions))
     self.assertEqual(["ENUM"], [enum.__name__ for enum in enums])
     [enum] = enums
     # Because the module has been executed in a different namespace, the
     # enum we've found is not the same object as the one in the current
     # global namespace.
     self.assertIsNot(ENUM, enum)
     # It does, however, have the same values.
     self.assertEqual(map_enum(ENUM), map_enum(enum))
Esempio n. 3
0
class TestRenderPreseed(MAASServerTestCase):
    """Tests for `render_preseed`.

    These tests check that the templates render (i.e. that no variable is
    missing).
    """

    # Create a scenario for each possible value of PRESEED_TYPE except
    # enlistment. Those have their own test case.
    scenarios = [(name, {
        'preseed': value
    }) for name, value in map_enum(PRESEED_TYPE).items()
                 if not value.startswith('enlist')]

    def test_render_preseed(self):
        node = factory.make_node()
        preseed = render_preseed(node, self.preseed, "precise")
        # The test really is that the preseed is rendered without an
        # error.
        self.assertIsInstance(preseed, bytes)

    def test_get_preseed_uses_nodegroup_maas_url(self):
        ng_url = 'http://%s' % factory.make_hostname()
        ng = factory.make_node_group(maas_url=ng_url)
        maas_url = 'http://%s' % factory.make_hostname()
        node = factory.make_node(nodegroup=ng,
                                 status=NODE_STATUS.COMMISSIONING)
        self.patch(settings, 'DEFAULT_MAAS_URL', maas_url)
        preseed = render_preseed(node, self.preseed, "precise")
        self.assertThat(
            preseed, MatchesAll(
                *[Contains(ng_url), Not(Contains(maas_url))]))
Esempio n. 4
0
    def test_accept_enlistment_rejects_bad_state_change(self):
        # If a node is neither Declared nor in one of the "accepted"
        # states where acceptance is a safe no-op, accept_enlistment
        # raises a node state violation and leaves the node's state
        # unchanged.
        all_states = map_enum(NODE_STATUS).values()
        acceptable_states = [
            NODE_STATUS.DECLARED,
            NODE_STATUS.COMMISSIONING,
            NODE_STATUS.READY,
            ]
        unacceptable_states = set(all_states) - set(acceptable_states)
        nodes = {
            status: factory.make_node(status=status)
            for status in unacceptable_states}

        exceptions = {status: False for status in unacceptable_states}
        for status, node in nodes.items():
            try:
                node.accept_enlistment(factory.make_user())
            except NodeStateViolation:
                exceptions[status] = True

        self.assertEqual(
            {status: True for status in unacceptable_states}, exceptions)
        self.assertEqual(
            {status: status for status in unacceptable_states},
            {status: node.status for status, node in nodes.items()})
Esempio n. 5
0
    def test_POST_accept_rejects_impossible_state_changes(self):
        self.become_admin()
        acceptable_states = set([
            NODE_STATUS.DECLARED,
            NODE_STATUS.COMMISSIONING,
            NODE_STATUS.READY,
            ])
        unacceptable_states = (
            set(map_enum(NODE_STATUS).values()) - acceptable_states)
        nodes = {
            status: factory.make_node(status=status)
            for status in unacceptable_states}
        responses = {
            status: self.client.post(
                reverse('nodes_handler'), {
                    'op': 'accept',
                    'nodes': [node.system_id],
                    })
            for status, node in nodes.items()}
        # All of these attempts are rejected with Conflict errors.
        self.assertEqual(
            {status: httplib.CONFLICT for status in unacceptable_states},
            {
                status: responses[status].status_code
                for status in unacceptable_states})

        for status, response in responses.items():
            # Each error describes the problem.
            self.assertIn("Cannot accept node enlistment", response.content)
            # Each error names the node it encountered a problem with.
            self.assertIn(nodes[status].system_id, response.content)
            # Each error names the node state that the request conflicted
            # with.
            self.assertIn(NODE_STATUS_CHOICES_DICT[status], response.content)
Esempio n. 6
0
 def test_POST_release_rejects_impossible_state_changes(self):
     acceptable_states = {
         NODE_STATUS.ALLOCATED,
         NODE_STATUS.RESERVED,
         NODE_STATUS.READY,
         }
     unacceptable_states = (
         set(map_enum(NODE_STATUS).values()) - acceptable_states)
     owner = self.logged_in_user
     nodes = [
         factory.make_node(status=status, owner=owner)
         for status in unacceptable_states]
     response = self.client.post(
         reverse('nodes_handler'), {
             'op': 'release',
             'nodes': [node.system_id for node in nodes],
             })
     # Awkward parsing again, because a string is returned, not JSON
     expected = [
         "%s ('%s')" % (node.system_id, node.display_status())
         for node in nodes
         if node.status not in acceptable_states]
     s = response.content
     returned = s[s.rfind(':') + 2:s.rfind('.')].split(', ')
     self.assertEqual(httplib.CONFLICT, response.status_code)
     self.assertIn(
         "Node(s) cannot be released in their current state:",
         response.content)
     self.assertItemsEqual(expected, returned)
Esempio n. 7
0
 def test_POST_release_rejects_impossible_state_changes(self):
     acceptable_states = {
         NODE_STATUS.ALLOCATED,
         NODE_STATUS.RESERVED,
         NODE_STATUS.READY,
     }
     unacceptable_states = (set(map_enum(NODE_STATUS).values()) -
                            acceptable_states)
     owner = self.logged_in_user
     nodes = [
         factory.make_node(status=status, owner=owner)
         for status in unacceptable_states
     ]
     response = self.client.post(
         reverse('nodes_handler'), {
             'op': 'release',
             'nodes': [node.system_id for node in nodes],
         })
     # Awkward parsing again, because a string is returned, not JSON
     expected = [
         "%s ('%s')" % (node.system_id, node.display_status())
         for node in nodes if node.status not in acceptable_states
     ]
     s = response.content
     returned = s[s.rfind(':') + 2:s.rfind('.')].split(', ')
     self.assertEqual(httplib.CONFLICT, response.status_code)
     self.assertIn("Node(s) cannot be released in their current state:",
                   response.content)
     self.assertItemsEqual(expected, returned)
Esempio n. 8
0
    def test_accept_enlistment_rejects_bad_state_change(self):
        # If a node is neither Declared nor in one of the "accepted"
        # states where acceptance is a safe no-op, accept_enlistment
        # raises a node state violation and leaves the node's state
        # unchanged.
        all_states = map_enum(NODE_STATUS).values()
        acceptable_states = [
            NODE_STATUS.DECLARED,
            NODE_STATUS.COMMISSIONING,
            NODE_STATUS.READY,
            ]
        unacceptable_states = set(all_states) - set(acceptable_states)
        nodes = {
            status: factory.make_node(status=status)
            for status in unacceptable_states}

        exceptions = {status: False for status in unacceptable_states}
        for status, node in nodes.items():
            try:
                node.accept_enlistment(factory.make_user())
            except NodeStateViolation:
                exceptions[status] = True

        self.assertEqual(
            {status: True for status in unacceptable_states}, exceptions)
        self.assertEqual(
            {status: status for status in unacceptable_states},
            {status: node.status for status, node in nodes.items()})
Esempio n. 9
0
    def test_map_enum_includes_all_enum_values(self):

        class Enum:
            ONE = 1
            TWO = 2

        self.assertItemsEqual(['ONE', 'TWO'], map_enum(Enum).keys())
Esempio n. 10
0
    def test_map_enum_maps_values(self):

        class Enum:
            ONE = 1
            THREE = 3

        self.assertEqual({'ONE': 1, 'THREE': 3}, map_enum(Enum))
Esempio n. 11
0
 def test_refresh_workers_skips_unaccepted_cluster_controllers(self):
     self.patch(nodegroup_module, 'refresh_worker')
     for status in map_enum(NODEGROUP_STATUS).values():
         if status != NODEGROUP_STATUS.ACCEPTED:
             factory.make_node_group(status=status)
     NodeGroup.objects.refresh_workers()
     self.assertEqual(0, nodegroup_module.refresh_worker.call_count)
Esempio n. 12
0
 def test_refresh_workers_skips_unaccepted_cluster_controllers(self):
     self.patch(nodegroup_module, 'refresh_worker')
     for status in map_enum(NODEGROUP_STATUS).values():
         if status != NODEGROUP_STATUS.ACCEPTED:
             factory.make_node_group(status=status)
     NodeGroup.objects.refresh_workers()
     self.assertEqual(0, nodegroup_module.refresh_worker.call_count)
Esempio n. 13
0
class TestRenderEnlistmentPreseed(MAASServerTestCase):
    """Tests for `render_enlistment_preseed`."""

    # Create a scenario for each possible value of PRESEED_TYPE for
    # enlistment. The rest have their own test case.
    scenarios = [(name, {
        'preseed': value
    }) for name, value in map_enum(PRESEED_TYPE).items()
                 if value.startswith('enlist')]

    def test_render_enlistment_preseed(self):
        preseed = render_enlistment_preseed(self.preseed, "precise")
        # The test really is that the preseed is rendered without an
        # error.
        self.assertIsInstance(preseed, bytes)

    def test_render_enlistment_preseed_valid_yaml(self):
        preseed = render_enlistment_preseed(self.preseed, "precise")
        self.assertTrue(yaml.safe_load(preseed))

    def test_get_preseed_uses_nodegroup_maas_url(self):
        ng_url = 'http://%s' % factory.make_hostname()
        maas_url = 'http://%s' % factory.make_hostname()
        self.patch(settings, 'DEFAULT_MAAS_URL', maas_url)
        nodegroup = factory.make_node_group(maas_url=ng_url)
        preseed = render_enlistment_preseed(self.preseed,
                                            "precise",
                                            nodegroup=nodegroup)
        self.assertThat(
            preseed, MatchesAll(
                *[Contains(ng_url), Not(Contains(maas_url))]))
Esempio n. 14
0
 def test_get_effective_power_type_reads_node_field(self):
     power_types = list(map_enum(POWER_TYPE).values())
     power_types.remove(POWER_TYPE.DEFAULT)
     nodes = [
         factory.make_node(power_type=power_type)
         for power_type in power_types]
     self.assertEqual(
         power_types, [node.get_effective_power_type() for node in nodes])
Esempio n. 15
0
 def test_get_effective_power_type_reads_node_field(self):
     power_types = list(map_enum(POWER_TYPE).values())
     power_types.remove(POWER_TYPE.DEFAULT)
     nodes = [
         factory.make_node(power_type=power_type)
         for power_type in power_types]
     self.assertEqual(
         power_types, [node.get_effective_power_type() for node in nodes])
Esempio n. 16
0
 def test_get_effective_power_type_defaults_to_config(self):
     power_types = list(map_enum(POWER_TYPE).values())
     power_types.remove(POWER_TYPE.DEFAULT)
     node = factory.make_node(power_type=POWER_TYPE.DEFAULT)
     effective_types = []
     for power_type in power_types:
         Config.objects.set_config('node_power_type', power_type)
         effective_types.append(node.get_effective_power_type())
     self.assertEqual(power_types, effective_types)
Esempio n. 17
0
 def test_get_effective_power_type_defaults_to_config(self):
     power_types = list(map_enum(POWER_TYPE).values())
     power_types.remove(POWER_TYPE.DEFAULT)
     node = factory.make_node(power_type=POWER_TYPE.DEFAULT)
     effective_types = []
     for power_type in power_types:
         Config.objects.set_config('node_power_type', power_type)
         effective_types.append(node.get_effective_power_type())
     self.assertEqual(power_types, effective_types)
Esempio n. 18
0
    def getRandomEnum(self, enum, but_not=None):
        """Pick a random item from an enumeration class.

        :param enum: An enumeration class such as `NODE_STATUS`.
        :return: The value of one of its items.
        :param but_not: A list of choices' IDs to exclude.
        :type but_not: Sequence.
        """
        if but_not is None:
            but_not = ()
        return random.choice([
            value for value in list(map_enum(enum).values())
            if value not in but_not])
Esempio n. 19
0
 def test_view_node_shows_message_for_commissioning_node(self):
     statuses_with_message = (
         NODE_STATUS.READY, NODE_STATUS.COMMISSIONING)
     help_link = "https://wiki.ubuntu.com/ServerTeam/MAAS/AvahiBoot"
     for status in map_enum(NODE_STATUS).values():
         node = factory.make_node(status=status)
         node_link = reverse('node-view', args=[node.system_id])
         response = self.client.get(node_link)
         links = get_content_links(response, '#flash-messages')
         if status in statuses_with_message:
             self.assertIn(help_link, links)
         else:
             self.assertNotIn(help_link, links)
Esempio n. 20
0
    def getRandomEnum(self, enum, but_not=None):
        """Pick a random item from an enumeration class.

        :param enum: An enumeration class such as `NODE_STATUS`.
        :return: The value of one of its items.
        :param but_not: A list of choices' IDs to exclude.
        :type but_not: Sequence.
        """
        if but_not is None:
            but_not = ()
        return random.choice([
            value for value in list(map_enum(enum).values())
            if value not in but_not
        ])
Esempio n. 21
0
    def test_map_enum_omits_private_or_special_methods(self):
        class Enum:
            def __init__(self):
                pass

            def __repr__(self):
                return "Enum"

            def _save(self):
                pass

            VALUE = 9

        self.assertItemsEqual(['VALUE'], map_enum(Enum).keys())
Esempio n. 22
0
    def test_map_enum_omits_private_or_special_methods(self):

        class Enum:
            def __init__(self):
                pass

            def __repr__(self):
                return "Enum"

            def _save(self):
                pass

            VALUE = 9

        self.assertItemsEqual(['VALUE'], map_enum(Enum).keys())
Esempio n. 23
0
class UseDI(NodeAction):
    """Set this node to use d-i for installation."""
    name = "usedi"
    display = "Use the default installer"
    display_bulk = "Mark nodes as using the default installer"
    actionable_statuses = map_enum(NODE_STATUS).values()
    permission = NODE_PERMISSION.EDIT

    def is_permitted(self):
        permitted = super(UseDI, self).is_permitted()
        return permitted and self.node.should_use_fastpath_installer()

    def execute(self, allow_redirect=True):
        """See `NodeAction.execute`."""
        self.node.use_traditional_installer()
        return "Node marked as using the default installer."
Esempio n. 24
0
 def test_POST_release_fails_for_other_node_states(self):
     releasable_statuses = [
         NODE_STATUS.RESERVED,
         NODE_STATUS.ALLOCATED,
         NODE_STATUS.READY,
         ]
     unreleasable_statuses = [
         status
         for status in map_enum(NODE_STATUS).values()
         if status not in releasable_statuses
     ]
     nodes = [
         factory.make_node(status=status, owner=self.logged_in_user)
         for status in unreleasable_statuses]
     responses = [
         self.client.post(self.get_node_uri(node), {'op': 'release'})
         for node in nodes]
     self.assertEqual(
         [httplib.CONFLICT] * len(unreleasable_statuses),
         [response.status_code for response in responses])
     self.assertItemsEqual(
         unreleasable_statuses,
         [node.status for node in reload_objects(Node, nodes)])
Esempio n. 25
0
    def test_POST_accept_rejects_impossible_state_changes(self):
        self.become_admin()
        acceptable_states = set([
            NODE_STATUS.DECLARED,
            NODE_STATUS.COMMISSIONING,
            NODE_STATUS.READY,
        ])
        unacceptable_states = (set(map_enum(NODE_STATUS).values()) -
                               acceptable_states)
        nodes = {
            status: factory.make_node(status=status)
            for status in unacceptable_states
        }
        responses = {
            status: self.client.post(reverse('nodes_handler'), {
                'op': 'accept',
                'nodes': [node.system_id],
            })
            for status, node in nodes.items()
        }
        # All of these attempts are rejected with Conflict errors.
        self.assertEqual(
            {status: httplib.CONFLICT
             for status in unacceptable_states}, {
                 status: responses[status].status_code
                 for status in unacceptable_states
             })

        for status, response in responses.items():
            # Each error describes the problem.
            self.assertIn("Cannot accept node enlistment", response.content)
            # Each error names the node it encountered a problem with.
            self.assertIn(nodes[status].system_id, response.content)
            # Each error names the node state that the request conflicted
            # with.
            self.assertIn(NODE_STATUS_CHOICES_DICT[status], response.content)
Esempio n. 26
0
 def test_POWER_TYPE_PARAMETERS_is_dict_with_power_type_keys(self):
     power_types = set(map_enum(POWER_TYPE).values())
     self.assertIsInstance(POWER_TYPE_PARAMETERS, dict)
     self.assertThat(power_types, ContainsAll(POWER_TYPE_PARAMETERS))
Esempio n. 27
0
from maasserver.utils import map_enum
import maastesting.factory
from maastesting.factory import NO_VALUE
from metadataserver.fields import Bin
from metadataserver.models import (
    CommissioningScript,
    NodeCommissionResult,
    )
from netaddr import IPAddress

# We have a limited number of public keys:
# src/maasserver/tests/data/test_rsa{0, 1, 2, 3, 4}.pub
MAX_PUBLIC_KEYS = 5


ALL_NODE_STATES = map_enum(NODE_STATUS).values()


class Factory(maastesting.factory.Factory):

    def make_file_upload(self, name=None, content=None):
        """Create a file-like object for upload in http POST or PUT.

        To upload a file using the Django test client, just include a
        parameter that maps not to a string, but to a file upload as
        produced by this method.

        :param name: Name of the file to be uploaded.  If omitted, one will
            be made up.
        :type name: `unicode`
        :param content: Contents for the uploaded file.  If omitted, some
Esempio n. 28
0
)
from maasserver.utils import map_enum
import maastesting.factory
from maastesting.factory import NO_VALUE
from metadataserver.fields import Bin
from metadataserver.models import (
    CommissioningScript,
    NodeCommissionResult,
)
from netaddr import IPAddress

# We have a limited number of public keys:
# src/maasserver/tests/data/test_rsa{0, 1, 2, 3, 4}.pub
MAX_PUBLIC_KEYS = 5

ALL_NODE_STATES = map_enum(NODE_STATUS).values()


class Factory(maastesting.factory.Factory):
    def make_file_upload(self, name=None, content=None):
        """Create a file-like object for upload in http POST or PUT.

        To upload a file using the Django test client, just include a
        parameter that maps not to a string, but to a file upload as
        produced by this method.

        :param name: Name of the file to be uploaded.  If omitted, one will
            be made up.
        :type name: `unicode`
        :param content: Contents for the uploaded file.  If omitted, some
            contents will be made up.
Esempio n. 29
0
def serialize_enum(enum):
    """Represent a MAAS enum class in JavaScript."""
    return "module.%s = %s;\n" % (
        enum.__name__,
        json.dumps(map_enum(enum), indent=4, sort_keys=True))
Esempio n. 30
0
def get_random_component():
    return random.choice(map_enum(COMPONENT).values())
Esempio n. 31
0
    def test_map_enum_maps_values(self):
        class Enum:
            ONE = 1
            THREE = 3

        self.assertEqual({'ONE': 1, 'THREE': 3}, map_enum(Enum))
Esempio n. 32
0
 def test_POWER_TYPE_PARAMETERS_is_dict_with_power_type_keys(self):
     power_types = set(map_enum(POWER_TYPE).values())
     self.assertIsInstance(POWER_TYPE_PARAMETERS, dict)
     self.assertThat(power_types, ContainsAll(POWER_TYPE_PARAMETERS))
Esempio n. 33
0
def serialize_enum(enum):
    """Represent a MAAS enum class in JavaScript."""
    return "module.%s = %s;\n" % (
        enum.__name__, json.dumps(map_enum(enum), indent=4, sort_keys=True))
Esempio n. 34
0
def get_random_component():
    return random.choice(map_enum(COMPONENT).values())
Esempio n. 35
0
    def test_map_enum_includes_all_enum_values(self):
        class Enum:
            ONE = 1
            TWO = 2

        self.assertItemsEqual(['ONE', 'TWO'], map_enum(Enum).keys())