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