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