def delete_snapshot_schedule(self, container, lun=None, lungroup=None, schedule_name=None, delete_snapshots=None): """ Delete a snapshot schedule. Arguments: container -- string lun -- string (optional) lungroup -- string (optional) schedule_name -- string (optional) delete_snapshots -- bool (optional) Returns: Action result as a dict. """ nodes = [] nodes.append(XGNode('container', 'string', container)) if lun is not None: nodes.append(XGNode('lun', 'string', lun)) if lungroup is not None: nodes.append(XGNode('lungroup', 'string', lungroup)) if schedule_name is not None: nodes.append(XGNode('schedule_name', 'string', schedule_name)) if delete_snapshots is not None: nodes.append(XGNode('delete_snapshots', 'bool', delete_snapshots)) return self._basic.perform_action( '/vshare/actions/vdm' + '/schedule/snapshot/delete', nodes)
def _igroup_create(self, igroup, delete): """ Internal work function for: create_igroup delete_igroup """ nodes = [] nodes.append(XGNode('igroup', 'string', igroup)) nodes.append(XGNode('delete', 'bool', delete)) return self._basic.perform_action('/vshare/actions' + '/igroup/create', nodes)
def _iscsi_target_create(self, target, create): """ Internal work function for: create_iscsi_target delete_iscsi_target """ nodes = [] nodes.append(XGNode('target', 'string', target)) nodes.append(XGNode('create', 'bool', create)) return self._basic.perform_action( '/vshare/actions' + '/iscsi/target/create', nodes)
def _iscsi_target_bind(self, target, ip, add): """ Internal work function for: bind_ip_to_target unbind_ip_from_target """ nodes = [] nodes.append(XGNode('target', 'string', target)) nodes.extend(XGNode.as_node_list('ip/{0}', 'string', ip)) nodes.append(XGNode('add', 'bool', add)) return self._basic.perform_action( '/vshare/actions' + '/iscsi/target/bind', nodes)
def _igroup_modify(self, igroup, initiators, delete): """ Internal work function for: add_initiators delete_initiators """ nodes = [] nodes.append(XGNode('igroup', 'string', igroup)) nodes.extend( XGNode.as_node_list('initiators/{0}', 'string', initiators)) nodes.append(XGNode('delete', 'bool', delete)) return self._basic.perform_action('/vshare/actions' + '/igroup/modify', nodes)
def format_array(self, percentage, volumeid=None): """ Format the array. Arguments: percentage -- uint8 volumeid -- uint32 """ nodes = [] nodes.append(XGNode('percentage', 'uint8', percentage)) if volumeid: nodes.append(XGNode('volumeid', 'uint32', volumeid)) return self._basic.perform_action('/array/actions' + '/format', nodes)
def _get_nodes(self, node_names, nostate=False, noconfig=False, flat=False, values_only=False, strip=None): query_flags = [] if nostate: query_flags.append("no-state") if noconfig: query_flags.append("no-config") # Convert basestring to list, so we can accept either now if isinstance(node_names, basestring): node_names = [node_names] nodes = [] for n in node_names: nodes.append(XGNode(n, flags=query_flags)) req = XGQuery(nodes, flat, values_only) resp = self.send_request(req, strip) # TODO(gfreeman): If we have send_request return empty nodes # dict rather than None for error we can eliminate this # conditional. return resp.nodes
def _lungroup_export(self, container, name, initiators, ports, unexport): """ Internal work function for: export_lun_group unexport_lun_group """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('name', 'string', name)) nodes.extend(XGNode.as_node_list('initiators/{0}', 'string', initiators)) nodes.extend(XGNode.as_node_list('ports/{0}', 'string', ports)) nodes.append(XGNode('unexport', 'bool', unexport)) return self._basic.perform_action('/vshare/actions/vdm' + '/lungroup/export', nodes)
def rename_igroup(self, old_igroup, new_igroup): """ Renames an igroup. Arguments: old_igroup -- string new_igroup -- string Returns: Action result as a dict. """ nodes = [] nodes.append(XGNode('old_igroup', 'string', old_igroup)) nodes.append(XGNode('new_igroup', 'string', new_igroup)) return self._basic.perform_action('/vshare/actions' + '/igroup/rename', nodes)
def set_lun_snapshot(self, container, lun, name, new_name=None, description=None, readwrite=None, snap_protect=None, port_A=None, port_B=None): """ Update a LUN snapshot. Arguments: container -- string lun -- string name -- string new_name -- string (optional) description -- string (optional) readwrite -- bool (optional) snap_protect -- bool (optional) port_A -- bool (optional) port_B -- bool (optional) Returns: Action result as a dict. """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('lun', 'string', lun)) nodes.append(XGNode('name', 'string', name)) if new_name is not None: nodes.append(XGNode('new_name', 'string', new_name)) if description is not None: nodes.append(XGNode('description', 'string', description)) if readwrite is not None: nodes.append(XGNode('readwrite', 'bool', readwrite)) if snap_protect is not None: nodes.append(XGNode('snap_protect', 'bool', snap_protect)) if port_A is not None: nodes.append(XGNode('port_A', 'bool', port_A)) if port_B is not None: nodes.append(XGNode('port_B', 'bool', port_B)) return self._basic.perform_action( '/vshare/actions/vdm' + '/snapshot/set', nodes)
def rollback_lun_group(self, container, lungroup, name): """ Rollback a LUN group to the specified snapshot. Arguments: container -- string lungroup -- string name -- string Returns: Action result as a dict. """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('lungroup', 'string', lungroup)) nodes.append(XGNode('name', 'string', name)) return self._basic.perform_action( '/vshare/actions/vdm' + '/snapgroup/rollback', nodes)
def _iscsi_global(self, enable): """ Internal work function for: enable_iscsi_globally disable_iscsi_globally """ nodes = [] nodes.append(XGNode('enable', 'bool', enable)) return self._basic.perform_action( '/vshare/actions' + '/iscsi/enable_global', nodes)
def _snapshot_export(self, container, lun, names, initiators, ports, lun_id, unexport, force): """Internal work function for: export_lun_snapshot unexport_lun_snapshot """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('lun', 'string', lun)) nodes.extend(XGNode.as_node_list('names/{0}', 'string', names)) nodes.extend(XGNode.as_node_list('initiators/{0}', 'string', initiators)) nodes.extend(XGNode.as_node_list('ports/{0}', 'string', ports)) nodes.append(XGNode('lun_id', 'string', lun_id)) nodes.append(XGNode('unexport', 'bool', unexport)) if force is not None: nodes.append(XGNode('force', 'bool', force)) return self._basic.perform_action('/vshare/actions/vdm' + '/snapshot/export', nodes)
def _lun_export(self, container, names, ports, initiators, lun_id, unexport): """ Internal work function for: export_lun unexport_lun """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.extend(XGNode.as_node_list('names/{0}', 'string', names)) nodes.extend(XGNode.as_node_list('initiators/{0}', 'string', initiators)) nodes.extend(XGNode.as_node_list('ports/{0}', 'string', ports)) if lun_id == 'auto': nodes.append(XGNode('lun_id', 'int16', -1)) else: nodes.append(XGNode('lun_id', 'int16', lun_id)) nodes.append(XGNode('unexport', 'bool', unexport)) return self._basic.perform_action('/vshare/actions' + '/lun/export', nodes)
def _iscsi_target_bind(self, target, ip, add): """Internal work function for: bind_ip_to_target unbind_ip_from_target """ nodes = [] nodes.append(XGNode('target', 'string', target)) nodes.extend(XGNode.as_node_list('ip/{0}', 'string', ip)) nodes.append(XGNode('add', 'bool', add)) return self._basic.perform_action('/vshare/actions' + '/iscsi/target/bind', nodes)
def _igroup_modify(self, igroup, initiators, delete): """ Internal work function for: add_initiators delete_initiators """ nodes = [] nodes.append(XGNode("igroup", "string", igroup)) nodes.extend(XGNode.as_node_list("initiators/{0}", "string", initiators)) nodes.append(XGNode("delete", "bool", delete)) return self._basic.perform_action("/vshare/actions" + "/igroup/modify", nodes)
def _igroup_modify(self, igroup, initiators, delete): """Internal work function for: add_initiators delete_initiators """ nodes = [] nodes.append(XGNode('igroup', 'string', igroup)) nodes.extend(XGNode.as_node_list('initiators/{0}', 'string', initiators)) nodes.append(XGNode('delete', 'bool', delete)) return self._basic.perform_action('/vshare/actions' + '/igroup/modify', nodes)
def bulk_delete_luns(self, container, luns): """ Delete one or more LUNs. Arguments: container -- string luns -- string (string or list) Returns: Action result as a dict. """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.extend(XGNode.as_node_list('lun/{0}', 'string', luns)) return self._basic.perform_action('/vshare/actions' + '/lun/bulk_delete', nodes)
def _lungroup_create(self, container, name, lun_names, action, description): """ Internal work function for: create_lun_group delete_lun_group """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('name', 'string', name)) nodes.extend(XGNode.as_node_list('lun_names/{0}', 'string', lun_names)) nodes.append(XGNode('action', 'string', action)) if description is not None: nodes.append(XGNode('description', 'string', description)) return self._basic.perform_action('/vshare/actions/vdm' + '/lungroup/create', nodes)
def _snapshot_export(self, container, lun, names, initiators, ports, lun_id, unexport, force): """ Internal work function for: export_lun_snapshot unexport_lun_snapshot """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('lun', 'string', lun)) nodes.extend(XGNode.as_node_list('names/{0}', 'string', names)) nodes.extend( XGNode.as_node_list('initiators/{0}', 'string', initiators)) nodes.extend(XGNode.as_node_list('ports/{0}', 'string', ports)) nodes.append(XGNode('lun_id', 'string', lun_id)) nodes.append(XGNode('unexport', 'bool', unexport)) if force is not None: nodes.append(XGNode('force', 'bool', force)) return self._basic.perform_action( '/vshare/actions/vdm' + '/snapshot/export', nodes)
def _lungroup_update(self, container, name, new_name, lun_names, remove, description): """ Internal work function for: add_to_lun_group remove_from_lun_group """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('name', 'string', name)) if new_name is not None: nodes.append(XGNode('new_name', 'string', new_name)) nodes.extend(XGNode.as_node_list('lun_names/{0}', 'string', lun_names)) if remove is not None: nodes.append(XGNode('remove', 'bool', remove)) if description is not None: nodes.append(XGNode('description', 'string', description)) return self._basic.perform_action('/vshare/actions/vdm' + '/lungroup/update', nodes)
def _snapshot_create(self, container, lun, name, action, description, readwrite, snap_protect): """ Internal work function for: create_lun_snapshot delete_lun_snapshot """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('lun', 'string', lun)) nodes.append(XGNode('name', 'string', name)) nodes.append(XGNode('action', 'string', action)) if description is not None: nodes.append(XGNode('description', 'string', description)) if readwrite is not None: nodes.append(XGNode('readwrite', 'bool', readwrite)) if snap_protect is not None: nodes.append(XGNode('snap_protect', 'bool', snap_protect)) return self._basic.perform_action( '/vshare/actions/vdm' + '/snapshot/create', nodes)
def _snapgroup_export(self, container, lungroup, name, initiators, ports, unexport): """ Internal work function for: export_lun_group_snapshot unexport_lun_group_snapshot """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('lungroup', 'string', lungroup)) nodes.append(XGNode('name', 'string', name)) nodes.extend( XGNode.as_node_list('initiators/{0}', 'string', initiators)) nodes.extend(XGNode.as_node_list('ports/{0}', 'string', ports)) nodes.append(XGNode('unexport', 'bool', unexport)) return self._basic.perform_action( '/vshare/actions/vdm' + '/snapgroup/export', nodes)
def fromstring(cls, request, xml_str, strip=None): """ Parse XML text contained in string and return as an XGResponse object for the given request type. Arguments: request - XGRequest object xml_str - string containing XML response to parse Returns: XGResponse object """ root_el = ET.fromstring(xml_str) if root_el.tag != "xg-response": raise ParseError("Not xg-response") else: xg_resp_el = root_el.getchildren()[0] if xg_resp_el.tag == "xg-status": # parse xg-status for child in xg_resp_el.getchildren(): if child.tag == "status-msg": r_msg = child.text elif child.tag == "status-code": r_code = child.text else: raise ParseError("Unknown status field.") # Handle authentication via Exception if r_msg == "Not authenticated": raise AuthenticationError(r_msg) return XGResponse("status", int(r_code), r_msg) elif xg_resp_el.tag != "%s-response" % (request.type): raise ParseError("Response type mismatch.") # Parse response # TODO(gfreeman): Refactor to not use find() ... loop through once ret_status_el = xg_resp_el.find("return-status") if ret_status_el is None: raise ParseError("Missing return-status field.") try: r_code = ret_status_el.find("return-code").text except AttributeError: raise ParseError("Missing return-code field.") try: r_msg = ret_status_el.find("return-msg").text except AttributeError: r_msg = "" try: db_rev = xg_resp_el.find("db-revision-id").text if not db_rev.isdigit(): raise ParseError("Non-numeric db-revision-id") except AttributeError: db_rev = "0" try: nodes_el = xg_resp_el.find("nodes") except AttributeError: raise ParseError("Missing nodes element.") # # Parse the return nodes per parameters in XGRequest # # If request.flat is True, we return a dict of nodes # keyed to node_name. If a returned node had no name # it will not be included. # # If request.flat is False, we return a LIST of nodes # that can contain subnodes. # # If values_only is True, we return node values rather # than XGNode objects. # nodes_d = {} nodes_l = [] if nodes_el is not None: for node in nodes_el.getchildren(): # parse node if node.tag != "node": raise ParseError("Unexpected subelement '%s'" % (node.tag, )) if request.flat: nodes_d.update( XGNode.parse_el(node, request.flat, strip=strip)) else: nodes_l.append( XGNode.parse_el(node, request.flat, strip=strip)) if request.flat: nodes = XGNodeDict(nodes_d, request.values_only) else: nodes = nodes_l return XGResponse(request.type, int(r_code), r_msg, db_rev, nodes)
def modify_snapshot_schedule(self, container, schedule_name, type, is_lungroup_schedule, lun_or_group_name, new_schedule_name=None, description=None, date=None, time=None, start_date=None, start_time=None, end_date=None, end_time=None, periodicity=None, days_of_week=None, monthly_interval=None, day_of_month=None, readwrite=None, protect=None, max_keep=None, enable=None): """ Modify a snapshot schedule. Arguments: container -- string schedule_name -- string type -- string is_lungroup_schedule -- bool lun_or_group_name -- string new_schedule_name -- string (optional) description -- string (optional) date -- date (string or datetime; optional) time -- time_sec (string or datetime; optional) start_date -- date (string or datetime; optional) start_time -- time_sec (string or datetime; optional) end_date -- date (string or datetime; optional) end_time -- time_sec (string or datetime; optional) periodicity -- duration_sec (string; optional) days_of_week -- string (optional) monthly_interval -- uint32 (optional) day_of_month -- int32 (optional) readwrite -- bool (optional) protect -- bool (optional) max_keep -- int32 (optional) enable -- bool (optional) Returns: Action result as a dict. """ nodes = [] nodes.append(XGNode('container', 'string', container)) nodes.append(XGNode('schedule_name', 'string', schedule_name)) nodes.append(XGNode('type', 'string', type)) nodes.append( XGNode('is_lungroup_schedule', 'bool', is_lungroup_schedule)) nodes.append(XGNode('lun_or_group_name', 'string', lun_or_group_name)) if new_schedule_name is not None: nodes.append( XGNode('new_schedule_name', 'string', new_schedule_name)) if description is not None: nodes.append(XGNode('description', 'string', description)) if date is not None: nodes.append(XGNode('date', 'date', date)) if time is not None: nodes.append(XGNode('time', 'time_sec', time)) if start_date is not None: nodes.append(XGNode('start_date', 'date', start_date)) if start_time is not None: nodes.append(XGNode('start_time', 'time_sec', start_time)) if end_date is not None: nodes.append(XGNode('end_date', 'date', end_date)) if end_time is not None: nodes.append(XGNode('end_time', 'time_sec', end_time)) if periodicity is not None: nodes.append(XGNode('periodicity', 'duration_sec', periodicity)) if days_of_week is not None: nodes.append(XGNode('days_of_week', 'string', days_of_week)) if monthly_interval is not None: nodes.append(XGNode('monthly_interval', 'uint32', monthly_interval)) if day_of_month is not None: nodes.append(XGNode('day_of_month', 'int32', day_of_month)) if readwrite is not None: nodes.append(XGNode('readwrite', 'bool', readwrite)) if protect is not None: nodes.append(XGNode('protect', 'bool', protect)) if max_keep is not None: nodes.append(XGNode('max_keep', 'int32', max_keep)) if enable is not None: nodes.append(XGNode('enable', 'bool', enable)) return self._basic.perform_action( '/vshare/actions/vdm' + '/schedule/snapshot/modify', nodes)
def fromstring(cls, request, xml_str, strip=None): """Parse XML text contained in string and return as an XGResponse object for the given request type. Arguments: request - XGRequest object xml_str - string containing XML response to parse Returns: XGResponse object """ root_el = ET.fromstring(xml_str) if root_el.tag != "xg-response": raise ParseError("Not xg-response") else: xg_resp_el = root_el.getchildren()[0] if xg_resp_el.tag == "xg-status": # parse xg-status for child in xg_resp_el.getchildren(): if child.tag == "status-msg": r_msg = child.text elif child.tag == "status-code": r_code = child.text else: raise ParseError("Unknown status field.") # Handle authentication via Exception if r_msg == "Not authenticated": raise AuthenticationError(r_msg) return XGResponse("status", int(r_code), r_msg) elif xg_resp_el.tag != "%s-response" % (request.type): raise ParseError("Response type mismatch.") # Parse response # TODO(gfreeman): Refactor to not use find() ... loop through once ret_status_el = xg_resp_el.find("return-status") if ret_status_el is None: raise ParseError("Missing return-status field.") try: r_code = ret_status_el.find("return-code").text except AttributeError: raise ParseError("Missing return-code field.") try: r_msg = ret_status_el.find("return-msg").text except AttributeError: r_msg = "" try: db_rev = xg_resp_el.find("db-revision-id").text if not db_rev.isdigit(): raise ParseError("Non-numeric db-revision-id") except AttributeError: db_rev = "0" try: nodes_el = xg_resp_el.find("nodes") except AttributeError: raise ParseError("Missing nodes element.") # # Parse the return nodes per parameters in XGRequest # # If request.flat is True, we return a dict of nodes # keyed to node_name. If a returned node had no name # it will not be included. # # If request.flat is False, we return a LIST of nodes # that can contain subnodes. # # If values_only is True, we return node values rather # than XGNode objects. # nodes_d = {} nodes_l = [] if nodes_el is not None: for node in nodes_el.getchildren(): # parse node if node.tag != "node": raise ParseError("Unexpected subelement '%s'" % (node.tag,)) if request.flat: nodes_d.update(XGNode.parse_el(node, request.flat, strip=strip)) else: nodes_l.append(XGNode.parse_el(node, request.flat, strip=strip)) if request.flat: nodes = XGNodeDict(nodes_d, request.values_only) else: nodes = nodes_l return XGResponse(request.type, int(r_code), r_msg, db_rev, nodes)