1#!/usr/bin/env python3
2
3r"""
4State Manager module:
5
6   - Defines Valid states of the system
7
8"""
9
10import gen_robot_keyword as keyword
11import variables as var
12
13import os
14import re
15import sys
16
17from robot.libraries.BuiltIn import BuiltIn
18
19robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
20repo_data_dir_path = re.sub('/lib', '/data', robot_pgm_dir_path)
21sys.path.append(repo_data_dir_path)
22
23
24BuiltIn().import_resource("state_manager.robot")
25BuiltIn().import_resource("rest_client.robot")
26
27platform_arch_type = os.environ.get('PLATFORM_ARCH_TYPE', '') or \
28    BuiltIn().get_variable_value("${PLATFORM_ARCH_TYPE}", default="power")
29
30# We will build eventually the mapping for warm, cold reset as well.
31VALID_STATES = {
32    'reboot':
33    {
34        # (Power Policy, BMC state, Chassis State, Host State)
35        ('LEAVE_OFF', 'Ready', 'Off', 'Off'),
36        ('ALWAYS_POWER_ON', 'Ready', 'On', 'Running'),
37        ('ALWAYS_POWER_ON', 'Ready', 'On', 'Off'),
38        ('RESTORE_LAST_STATE', 'Ready', 'On', 'Running'),
39        ('RESTORE_LAST_STATE', 'Ready', 'On', 'Off'),
40        ('ALWAYS_POWER_OFF', 'Ready', 'On', 'Running'),
41        ('ALWAYS_POWER_OFF', 'Ready', 'Off', 'Off'),
42    },
43}
44
45VALID_BOOT_STATES = {
46    'Off':  # Valid states when Host is Off.
47    {
48        # (BMC , Chassis , Host , BootProgress, OperatingSystemState)
49        (
50            "xyz.openbmc_project.State.BMC.BMCState.Ready",
51            "xyz.openbmc_project.State.Chassis.PowerState.Off",
52            "xyz.openbmc_project.State.Host.HostState.Off",
53            "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified",
54            "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive"
55        ),
56    },
57    'Reboot':  # Valid states when BMC reset to standby.
58    {
59        # (BMC , Chassis , Host , BootProgress, OperatingSystemState)
60        (
61            "xyz.openbmc_project.State.BMC.BMCState.Ready",
62            "xyz.openbmc_project.State.Chassis.PowerState.Off",
63            "xyz.openbmc_project.State.Host.HostState.Off",
64            "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified",
65            "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive"
66        ),
67    },
68    'Running':  # Valid states when Host is powering on.
69    {
70        # (BMC , Chassis , Host , BootProgress, OperatingSystemState)
71        (
72            "xyz.openbmc_project.State.BMC.BMCState.Ready",
73            "xyz.openbmc_project.State.Chassis.PowerState.On",
74            "xyz.openbmc_project.State.Host.HostState.Running",
75            "xyz.openbmc_project.State.Boot.Progress.ProgressStages.MotherboardInit",
76            "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive"
77        ),
78    },
79    'Booted':  # Valid state when Host is booted.
80    {
81        # (BMC , Chassis , Host , BootProgress, OperatingSystemState)
82        (
83            "xyz.openbmc_project.State.BMC.BMCState.Ready",
84            "xyz.openbmc_project.State.Chassis.PowerState.On",
85            "xyz.openbmc_project.State.Host.HostState.Running",
86            "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSStart",
87            "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.BootComplete"
88        ),
89    },
90    'ResetReload':  # Valid state BMC reset reload when host is booted.
91    {
92        # (BMC , Chassis , Host , BootProgress, OperatingSystemState)
93        (
94            "xyz.openbmc_project.State.BMC.BMCState.Ready",
95            "xyz.openbmc_project.State.Chassis.PowerState.On",
96            "xyz.openbmc_project.State.Host.HostState.Running",
97            "xyz.openbmc_project.State.Boot.Progress.ProgressStages.OSStart",
98            "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.BootComplete"
99        ),
100    },
101}
102REDFISH_VALID_BOOT_STATES = {
103    'Off':  # Valid states when Host is Off.
104    {
105        # (BMC , Chassis , Host , BootProgress)
106        (
107            "Enabled",
108            "Off",
109            "Disabled",
110            "None",
111        ),
112    },
113    'Reboot':  # Valid states when BMC reset to standby.
114    {
115        # (BMC , Chassis , Host , BootProgress)
116        (
117            "Enabled",
118            "Off",
119            "Disabled",
120            "None",
121        ),
122    },
123    'Running':  # Valid states when Host is powering on.
124    {
125        # (BMC , Chassis , Host , BootProgress)
126        (
127            "Enabled",
128            "On",
129            "Enabled",
130            "OSRunning",
131        ),
132    },
133    'Booted':  # Valid state when Host is booted.
134    {
135        # (BMC , Chassis , Host , BootProgress)
136        (
137            "Enabled",
138            "On",
139            "Enabled",
140            "OSRunning",
141        ),
142    },
143    'ResetReload':  # Valid state BMC reset reload when host is booted.
144    {
145        # (BMC , Chassis , Host , BootProgress)
146        (
147            "Enabled",
148            "On",
149            "Enabled",
150            "OSRunning",
151        ),
152    },
153}
154
155if platform_arch_type == "x86":
156    VALID_BOOT_STATES_X86 = {}
157    for state_name, state_set in VALID_BOOT_STATES.items():
158        VALID_BOOT_STATES_X86[state_name] = set()
159        for state_tuple in state_set:
160            state_tuple_new = tuple(
161                x
162                for x in state_tuple
163                if not (
164                    x.startswith("xyz.openbmc_project.State.Boot.Progress")
165                    or x.startswith("xyz.openbmc_project.State.OperatingSystem")
166                )
167            )
168            VALID_BOOT_STATES_X86[state_name].add(state_tuple_new)
169    VALID_BOOT_STATES = VALID_BOOT_STATES_X86
170
171
172class state_map():
173
174    def get_boot_state(self):
175        r"""
176        Return the system state as a tuple of bmc, chassis, host state,
177        BootProgress and OperatingSystemState.
178        """
179
180        status, state = keyword.run_key("Read Properties  "
181                                        + var.SYSTEM_STATE_URI + "enumerate")
182        bmc_state = state[var.SYSTEM_STATE_URI + 'bmc0']['CurrentBMCState']
183        chassis_state = \
184            state[var.SYSTEM_STATE_URI + 'chassis0']['CurrentPowerState']
185        host_state = state[var.SYSTEM_STATE_URI + 'host0']['CurrentHostState']
186        if platform_arch_type == "x86":
187            return (str(bmc_state),
188                    str(chassis_state),
189                    str(host_state))
190        else:
191            boot_state = state[var.SYSTEM_STATE_URI + 'host0']['BootProgress']
192            os_state = \
193                state[var.SYSTEM_STATE_URI + 'host0']['OperatingSystemState']
194
195            return (str(bmc_state),
196                    str(chassis_state),
197                    str(host_state),
198                    str(boot_state),
199                    str(os_state))
200
201    def valid_boot_state(self, boot_type, state_set):
202        r"""
203        Validate a given set of states is valid.
204
205        Description of argument(s):
206        boot_type                   Boot type (e.g. off/running/host booted
207                                    etc.)
208        state_set                   State set (e.g.bmc,chassis,host,
209                                    BootProgress,OperatingSystemState)
210        """
211
212        if state_set in set(VALID_BOOT_STATES[boot_type]):
213            return True
214        else:
215            return False
216
217    def redfish_valid_boot_state(self, boot_type, state_dict):
218        r"""
219        Validate a given set of states is valid.
220
221        Description of argument(s):
222        boot_type                   Boot type (e.g. off/running/host booted
223                                    etc.)
224        state_dict                  State dictionary.
225        """
226
227        if set(state_dict.values()) in set(REDFISH_VALID_BOOT_STATES[boot_type]):
228            return True
229        else:
230            return False
231