Stage DocstringΒΆ
The final part to developing a clean stage is writing the docstring. The docstring is used in the clean stage browser to let users know what the stage does, what arguments are available, and what the arguments default to. It also provides an example of using the stage in the clean YAML file.
The docstring should adhere to this general format:
"""<description>
Stage Schema
------------
<schema>
Example
-------
<example>
"""
This a complete example of a docstring for the stage we wrote in the previous sections. Be mindful of the indentation as multiline strings will contain leading whitespace if they exist which will then be rendered in the stage browser (which we dont want). Please use the same formatting for the schema.
1from genie.metaparser.util.schemaengine import Optional
2from genie.libs.clean import BaseStage
3
4class ChangeBootVariable(BaseStage):
5 """This stage configures boot variables of the device using the following steps:
6
7 - Delete existing boot variables.
8 - Configure boot variables using the provided 'images'.
9 - Set the configuration-register using the provided 'config_register'.
10 - Write memory.
11 - Verify the boot variables are as expected.
12 - Verify the configuration-register is as expected.
13
14Stage Schema
15------------
16change_boot_variable:
17
18 images (list): Image files to use when configuring the boot variables.
19
20 timeout (int, optional): Execute timeout in seconds. Defaults to 300.
21
22 config_register (str, optional): Value to set config-register for
23 reload. Defaults to 0x2102.
24
25 current_running_image (bool, optional): Set the boot variable to the currently
26 running image from the show version command instead of the image provided.
27 Defaults to False.
28
29Example
30-------
31change_boot_variable:
32 images:
33 - harddisk:/image.bin
34 timeout: 150
35"""
36
37 # ============
38 # Stage Schema
39 # ============
40 schema = {
41 Optional('images'): list,
42 Optional('timeout'): int,
43 Optional('config_register'): str,
44 Optional('current_running_image'): bool,
45 }
46
47 # =================
48 # Argument Defaults
49 # =================
50 TIMEOUT = 300
51 CONFIG_REGISTER = '0x2102'
52 CURRENT_RUNNING_IMAGE = False
53
54 # ==============================
55 # Execution order of Stage steps
56 # ==============================
57 exec_order = [
58 'delete_boot_variable',
59 'configure_boot_variable',
60 'set_configuration_register',
61 'write_memory',
62 'verify_boot_variable',
63 'verify_configuration_register'
64 ]
65
66 def delete_boot_variable(self, steps, device):
67
68 with steps.start("Delete any configure boot variables") as step:
69
70 try:
71 device.configure("no boot system")
72 except Exception as e:
73 step.failed("Failed to delete configured boot variables",
74 from_exception=e)
75
76 step.passed("Successfully deleted configured boot variables")
77
78 def configure_boot_variable(self, steps, device, images, timeout=TIMEOUT,
79 current_running_image=CURRENT_RUNNING_IMAGE):
80
81 with steps.start("Set boot variable to images provided for {}".format(
82 device.name)) as step:
83
84 if current_running_image:
85 log.info("Retrieving and using the running image due to "
86 "'current_running_image: True'")
87
88 try:
89 output = device.parse('show version')
90 images = [output['version']['system_image']]
91 except Exception as e:
92 step.failed("Failed to retrieve the running image. Cannot "
93 "set boot variables",
94 from_exception=e)
95
96 try:
97 device.api.execute_set_boot_variable(
98 boot_images=images, timeout=timeout)
99 except Exception as e:
100 step.failed("Failed to set boot variables to images provided",
101 from_exception=e)
102 else:
103 step.passed("Successfully set boot variables to images provided")
104
105 def set_configuration_register(self, steps, device,
106 config_register=CONFIG_REGISTER, timeout=TIMEOUT):
107 with steps.start("Set config register to boot new image on {}".format(
108 device.name)) as step:
109
110 try:
111 device.api.execute_set_config_register(
112 config_register=config_register, timeout=timeout)
113 except Exception as e:
114 step.failed("Failed to set config-register",
115 from_exception=e)
116 else:
117 step.passed("Successfully set config register")
118
119 def write_memory(self, steps, device, timeout=TIMEOUT):
120 with steps.start("Execute 'write memory' on {}".format(device.name)) as step:
121 try:
122 device.api.execute_write_memory(timeout=timeout)
123 except Exception as e:
124 step.failed("Failed to execute 'write memory'",
125 from_exception=e)
126 else:
127 step.passed("Successfully executed 'write memory'")
128
129 def verify_boot_variable(self, steps, device, images):
130 with steps.start("Verify next reload boot variables are correctly set "
131 "on {}".format(device.name)) as step:
132
133 if not device.api.verify_boot_variable(boot_images=images):
134 step.failed("Boot variables are NOT correctly set")
135 else:
136 step.passed("Boot variables are correctly set")
137
138 def verify_configuration_register(self, steps, device,
139 config_register=CONFIG_REGISTER):
140 with steps.start("Verify config-register is as expected on {}".format(
141 device.name)) as step:
142
143 if not device.api.verify_config_register(
144 config_register=config_register, next_reload=True):
145 step.failed("Config-register is not as expected")
146 else:
147 step.passed("Config-register is as expected")