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